Craig
Craig

Reputation: 18704

What is this VB6 method doing?

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

Answers (1)

xxbbcc
xxbbcc

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

Related Questions