Reputation: 18704
We are converting a VB6 application to C# (4.0). and have come across a method in VB6 that we're battling to understand.
Public Sub SaveToField(fldAttach As ADODB.Field)
Dim bData() As Byte
Dim nSize As Long
nSize = Len(m_sEmail)
bData = LngToByteArray(nSize)
fldAttach.AppendChunk bData
If nSize > 0 Then
bData = StringToByteArray(m_sEmail)
fldAttach.AppendChunk bData
End If
nSize = Len(m_sName)
bData = LngToByteArray(nSize)
fldAttach.AppendChunk bData
If nSize > 0 Then
bData = StringToByteArray(m_sName)
fldAttach.AppendChunk bData
End If
bData = LngToByteArray(m_nContactID)
fldAttach.AppendChunk bData
End Sub
It seems like it's doing some binary file copy type thing, but I'm not quite understanding. Could someone explain so that we can rewrite it?
Upvotes: 3
Views: 815
Reputation: 17347
It serializes the members of the current class (m_sEmail
, m_sName
, etc.) into the fldAttach
database field as a byte array. Each data element is prefixed with its size, that's why th code LngToByteArray(nSize)
is there for each piece of data written out.
In C# you'd use a MemoryStream
and BinaryWriter
to accomplish the serialization aspect of it and then you'd write the byte array from the memory stream to the database. Something like:
byte[] byData;
using (MemoryStream oStream = new MemoryStream)
{
using (BinaryWriter oWriter = new BinaryWriter (oStream))
{
if (m_sName == null)
{
oWriter.Write ((byte) 0); // null string
}
else
{
oWriter.Write ((byte) 1); // not a null string
oWriter.Write (m_sName);
}
// other fields
}
byData = oStream.ToArray (); // get serialized byte array
}
// use byData here
Edit: MarkJ pointed out in the comments that this code doesn't write the same binary format as the original VB6 code, only something similar. If there's an existing database with records written by the VB6 code, the C# code will have to handle those.
There are two major differences: one is how strings are output - the original VB6 code doesn't deal with null strings (there's no such concept in VB6). The other is that BinaryWriter.Write(string)
automatically writes a length-prefixed string - this may or may not be in the same exact format used by the VB6 code which outputs a length and then the string bytes. C# can replicate the VB6 code here using the following logic:
...
// assuming sStr is not null
byte[] byString = Encoding.Unicode.GetBytes ( sStr );
oWriter.Write ( sStr.Length );
oWriter.Write ( byString );
The C# port will have to assume no null strings or it'll have to deal with those in some way.
It may be better to write a small utility that goes through the database and updates all records to the new format in which strings have a null marker, a length-prefix and then the string bytes. I'd personally go with this solution since then new code doesn't have to deal with the quirks of and old language.
PS:
Do note that Long
in VB6 maps to int
in C#. This is important for handling the length prefix for the VB6 binary format.
Also, here's a link to a question about VB6 strings - this may be useful when porting happens:
VB6 equivalent of string.IsNullOrEmpty
Upvotes: 8