Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

VB6: How are binary files encoded? using Put statement

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#....

like image 592
Giora Ron Genender Avatar asked Jul 21 '26 04:07

Giora Ron Genender


1 Answers

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:\Users\Public\Documents\FplDb.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);
  }
}
like image 200
BlueMonkMN Avatar answered Jul 23 '26 16:07

BlueMonkMN



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!