3

我们正在将 VB6 应用程序转换为 C# (4.0)。并且在 VB6 中遇到了一种我们正在努力理解的方法。

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

似乎它正在做一些二进制文件复制类型的事情,但我不太了解。有人可以解释一下以便我们重写吗?

4

1 回答 1

8

它将当前类的成员( 、 等)作为字节数组序列化m_sEmailm_sName数据库fldAttach字段中。每个数据元素都以它的大小为前缀,这就是为什么LngToByteArray(nSize)写出的每条数据都有代码。

在 C# 中,您将使用MemoryStreamandBinaryWriter来完成它的序列化方面,然后将字节数组从内存流写入数据库。就像是:

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

编辑:MarkJ 在评论中指出,此代码编写的二进制格式与原始 VB6 代码不同,只有类似的内容。如果现有数据库中包含由 VB6 代码编写的记录,则 C# 代码必须处理这些记录。

有两个主要区别:一个是字符串的输出方式——原始的 VB6 代码不处理空字符串(VB6 中没有这样的概念)。另一个是BinaryWriter.Write(string)自动写入一个以长度为前缀的字符串——这可能与VB6代码使用的格式完全相同,VB6代码输出一个长度,然后是字符串字节。C# 可以使用以下逻辑在此处复制 VB6 代码:

...

// assuming sStr is not null
byte[] byString = Encoding.Unicode.GetBytes ( sStr );

oWriter.Write ( sStr.Length );
oWriter.Write ( byString );

C# 端口必须假定没有空字符串,否则必须以某种方式处理这些字符串。

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

于 2012-10-30T05:04:50.783 回答