我们正在将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
好像它正在做一些二进制文件复制类型的东西,但我不太了解。有人可以解释一下我们可以改写它吗?
答案 0 :(得分:8)
它将当前类(m_sEmail
,m_sName
等)的成员序列化为fldAttach
数据库字段作为字节数组。每个数据元素都以其大小为前缀,这就是为了写出每个数据的代码LngToByteArray(nSize)
的原因。
在C#中,你使用MemoryStream
和BinaryWriter
来完成它的序列化方面,然后你将字节数组从内存流写入数据库。类似的东西:
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代码使用的相同格式,后者输出长度,然后是字符串字节。 C#可以使用以下逻辑复制VB6代码:
...
// assuming sStr is not null
byte[] byString = Encoding.Unicode.GetBytes ( sStr );
oWriter.Write ( sStr.Length );
oWriter.Write ( byString );
C#端口必须假定没有空字符串,否则它必须以某种方式处理它们。
最好编写一个通过数据库的小实用程序,并将所有记录更新为新格式,其中字符串具有空标记,长度前缀,然后是字符串字节。我个人会使用这个解决方案,因为那时新代码不必处理古老语言的怪癖。
PS:
请注意,VB6中的Long
映射到C#中的int
。这对于处理VB6二进制格式的长度前缀非常重要。
此外,这里有一个关于VB6字符串问题的链接 - 这在移植时可能很有用: