VB6:二进制文件是如何编码的?使用 Put 语句

VB6: How are binary files encoded? using Put statement(VB6:二进制文件是如何编码的?使用 Put 语句)
本文介绍了VB6:二进制文件是如何编码的?使用 Put 语句的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

我有这个代码

 打开 WritingPath &"FplDb.txt" 随机为 #1 Len = Len(WpRec)对于 i = 1 到 99WpRec.WpIndex = FplDB(i, 1)WpRec.WpName = FplDB(i, 2)WpRec.WpLat = FplDB(i, 3)WpRec.WpLon = FplDB(i, 4)WpRec.WpLatDir = FplDB(i, 5)WpRec.WpLonDir = FplDB(i, 6)把#1, i, WpRec接下来我关闭 #1保存确定 = 1FplSave = SaveOk退出函数

此函数使用Open"和Put"语句将 99 个结构 (WpRec) 的矩阵二进制序列化为文件.但我不知道它是如何编码的......这对我来说很重要,因为我需要在 C# 中重写相同的序列化,但我需要知道使用什么编码方法,所以我可以在 C# 中做同样的事情...

解决方案

VB6 的棘手之处在于,您可以声明具有固定长度字符串的结构,这样您就可以编写包含不需要长度前缀的字符串的记录.字符串缓冲区的长度被编码到类型中,而不是需要与记录一起写出.这允许固定大小的记录.在 .NET 中,这有点被遗忘了,因为 VB.NET 有一种机制来支持它以实现向后兼容性,但据我所知,它并不是真正适用于 C#:如何在 VB.NET 中声明一个固定长度的字符串?.p>

.NET 似乎更倾向于写出带有长度前缀的字符串,这意味着记录通常是可变长度的.这是由 BinaryReader.ReadString.

但是,您可以使用 System.BitConverter 更好地控制记录如何序列化和反序列化为字节(System.IO.BinaryReader 和 System.IO.BinaryWriter 可能没有用,因为它们假设字符串具有长度前缀).请记住,VB6 Integer 映射到 .NET Int16,而 VB6 Long 是 .Net Int32.我不确切知道您是如何定义 VB6 结构的,但这里有一个可能的实现作为示例:

类程序{静态无效主要(字符串 [] 参数){WpRecType[] WpRec = 新 WpRecType[3];WpRec[0] = 新的 WpRecType();WpRec[0].WpIndex = 0;WpRec[0].WpName = "纽约";WpRec[0].WpLat = 40.783f;WpRec[0].WpLon = 73.967f;WpRec[0].WpLatDir = 1;WpRec[0].WpLonDir = 1;WpRec[1] = 新的 WpRecType();WpRec[1].WpIndex = 1;WpRec[1].WpName = "明尼阿波利斯";WpRec[1].WpLat = 44.983f;WpRec[1].WpLon = 93.233f;WpRec[1].WpLatDir = 1;WpRec[1].WpLonDir = 1;WpRec[2] = 新的 WpRecType();WpRec[2].WpIndex = 2;WpRec[2].WpName = "莫斯科";WpRec[2].WpLat = 55.75f;WpRec[2].WpLon = 37.6f;WpRec[2].WpLatDir = 1;WpRec[2].WpLonDir = 2;字节 [] 缓冲区 = 新字节 [WpRecType.RecordSize];使用(System.IO.FileStream stm =新 System.IO.FileStream(@"C:UsersPublicDocumentsFplDb.dat",System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite)){WpRec[0].SerializeInto(缓冲区);stm.Write(buffer, 0, buffer.Length);WpRec[1].SerializeInto(缓冲区);stm.Write(buffer, 0, buffer.Length);WpRec[2].SerializeInto(缓冲区);stm.Write(buffer, 0, buffer.Length);//寻找记录#1,加载并显示它stm.Seek(WpRecType.RecordSize * 1, System.IO.SeekOrigin.Begin);stm.Read(buffer, 0, WpRecType.RecordSize);WpRecType rec = 新 WpRecType(buffer);Console.WriteLine("[{0}] {1}: {2} {3}, {4} {5}", rec.WpIndex, rec.WpName,rec.WpLat, (rec.WpLatDir == 1) ?N":S",rec.WpLon, (rec.WpLonDir == 1) ?我们");}}}类 WpRecType{公开做空 WpIndex;公共字符串 WpName;公共单 WpLat;公共单WpLon;公共字节 WpLatDir;公共字节 WpLonDir;常量 int WpNameBytes = 40;//20 个 Unicode 字符公共常量 int RecordSize = WpNameBytes + 12;公共无效SerializeInto(字节[]目标){整数位置 = 0;目标.初始化();BitConverter.GetBytes(WpIndex).CopyTo(target, position);位置 += 2;System.Text.Encoding.Unicode.GetBytes(WpName).CopyTo(target, position);位置 += WpNameBytes;BitConverter.GetBytes(WpLat).CopyTo(target, position);位置 += 4;BitConverter.GetBytes(WpLon).CopyTo(target, position);位置 += 4;目标[位置++] = WpLatDir;目标[位置++] = WpLonDir;}公共无效反序列化(字节[]源){整数位置 = 0;WpIndex = BitConverter.ToInt16(源,位置);位置 += 2;WpName = System.Text.Encoding.Unicode.GetString(源,位置,WpNameBytes);位置 += WpNameBytes;WpLat = BitConverter.ToSingle(源,位置);位置 += 4;WpLon = BitConverter.ToSingle(源,位置);位置 += 4;WpLatDir = 源[位置++];WpLonDir = 源[位置++];}公共 WpRecType(){}公共 WpRecType(字节 [] 源){反序列化(源);}}

I have this code

  Open WritingPath & "FplDb.txt" For Random As #1 Len = Len(WpRec)
    For i = 1 To 99
      WpRec.WpIndex = FplDB(i, 1)
      WpRec.WpName = FplDB(i, 2)
      WpRec.WpLat = FplDB(i, 3)
      WpRec.WpLon = FplDB(i, 4)
      WpRec.WpLatDir = FplDB(i, 5)
      WpRec.WpLonDir = FplDB(i, 6)
      Put #1, i, WpRec
   Next i
   Close #1
   SaveOk = 1
   FplSave = SaveOk
   Exit Function

This function makes binary serialization of a matrix of 99 structs (WpRec) to file, using "Open" and "Put" statements. But I didn't get how it is encoded... It is important to me because I need to rewrite the same serialization in C# but I need to know what encoding method is used for that so I can do the same in C#....

解决方案

The tricky bit in VB6 was that you were allowed to declare structures with fixed length strings so that you could write records containing strings that didn't need a length prefix. The length of the string buffer was encoded into the type instead of needing to be written out with the record. This allowed for fixed size records. In .NET, this has kind of been left behind in the sense that VB.NET has a mechanism to support it for backward compatibility, but it's not really intended for C# as far as I can tell: How to declare a fixed-length string in VB.NET?.

.NET seems to have a preference for generally writing out strings with a length prefix, meaning that records are generally variable-length. This is suggested by the implementation of BinaryReader.ReadString.

However, you can use System.BitConverter to get finer control over how records are serialized and de-serialized as bytes (System.IO.BinaryReader and System.IO.BinaryWriter are probably not useful since they make assumptions that strings have a length prefix). Keep in mind that a VB6 Integer maps to a .NET Int16 and a VB6 Long is a .Net Int32. I don't know exactly how you have defined your VB6 structure, but here's one possible implementation as an example:

class Program
{
  static void Main(string[] args)
  {
     WpRecType[] WpRec = new WpRecType[3];
     WpRec[0] = new WpRecType();
     WpRec[0].WpIndex = 0;
     WpRec[0].WpName = "New York";
     WpRec[0].WpLat = 40.783f;
     WpRec[0].WpLon = 73.967f;
     WpRec[0].WpLatDir = 1;
     WpRec[0].WpLonDir = 1;
     WpRec[1] = new WpRecType();
     WpRec[1].WpIndex = 1;
     WpRec[1].WpName = "Minneapolis";
     WpRec[1].WpLat = 44.983f;
     WpRec[1].WpLon = 93.233f;
     WpRec[1].WpLatDir = 1;
     WpRec[1].WpLonDir = 1;
     WpRec[2] = new WpRecType();
     WpRec[2].WpIndex = 2;
     WpRec[2].WpName = "Moscow";
     WpRec[2].WpLat = 55.75f;
     WpRec[2].WpLon = 37.6f;
     WpRec[2].WpLatDir = 1;
     WpRec[2].WpLonDir = 2;
     byte[] buffer = new byte[WpRecType.RecordSize];
     using (System.IO.FileStream stm = 
        new System.IO.FileStream(@"C:UsersPublicDocumentsFplDb.dat",
        System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite))
     {
        WpRec[0].SerializeInto(buffer);
        stm.Write(buffer, 0, buffer.Length);
        WpRec[1].SerializeInto(buffer);
        stm.Write(buffer, 0, buffer.Length);
        WpRec[2].SerializeInto(buffer);
        stm.Write(buffer, 0, buffer.Length);

        // Seek to record #1, load and display it
        stm.Seek(WpRecType.RecordSize * 1, System.IO.SeekOrigin.Begin);
        stm.Read(buffer, 0, WpRecType.RecordSize);
        WpRecType rec = new WpRecType(buffer);
        Console.WriteLine("[{0}] {1}: {2} {3}, {4} {5}", rec.WpIndex, rec.WpName,
           rec.WpLat, (rec.WpLatDir == 1) ? "N" : "S",
           rec.WpLon, (rec.WpLonDir == 1) ? "W" : "E");
     }
  }
}

class WpRecType
{
  public short WpIndex;
  public string WpName;
  public Single WpLat;
  public Single WpLon;
  public byte WpLatDir;
  public byte WpLonDir;

  const int WpNameBytes = 40; // 20 unicode characters
  public const int RecordSize = WpNameBytes + 12;

  public void SerializeInto(byte[] target)
  {
     int position = 0;
     target.Initialize();
     BitConverter.GetBytes(WpIndex).CopyTo(target, position);
     position += 2;
     System.Text.Encoding.Unicode.GetBytes(WpName).CopyTo(target, position);
     position += WpNameBytes;
     BitConverter.GetBytes(WpLat).CopyTo(target, position);
     position += 4;
     BitConverter.GetBytes(WpLon).CopyTo(target, position);
     position += 4;
     target[position++] = WpLatDir;
     target[position++] = WpLonDir;
  }

  public void Deserialize(byte[] source)
  {
     int position = 0;
     WpIndex = BitConverter.ToInt16(source, position);
     position += 2;
     WpName = System.Text.Encoding.Unicode.GetString(source, position, WpNameBytes);
     position += WpNameBytes;
     WpLat = BitConverter.ToSingle(source, position);
     position += 4;
     WpLon = BitConverter.ToSingle(source, position);
     position += 4;
     WpLatDir = source[position++];
     WpLonDir = source[position++];
  }

  public WpRecType()
  {
  }

  public WpRecType(byte[] source)
  {
     Deserialize(source);
  }
}

这篇关于VB6:二进制文件是如何编码的?使用 Put 语句的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

本站部分内容来源互联网,如果有图片或者内容侵犯了您的权益,请联系我们,我们会在确认后第一时间进行删除!

相关文档推荐

Custom Error Queue Name when using EasyNetQ for RabbitMQ?(使用 EasyNetQ for RabbitMQ 时自定义错误队列名称?)
How to generate password_hash for RabbitMQ Management HTTP API(如何为 RabbitMQ 管理 HTTP API 生成密码哈希)
Rabbitmq Ack or Nack, leaving messages on the queue(Rabbitmq Ack 或 Nack,将消息留在队列中)
Setup RabbitMQ consumer in ASP.NET Core application(在 ASP.NET Core 应用程序中设置 RabbitMQ 消费者)
Specify Publish timeouts in mass transit(指定公共交通中的发布超时)
RabbitMQ asynchronous support(RabbitMQ 异步支持)