我正在重新创建一个较旧的 VB6 程序,该程序读取使用 VB.net 中的另一个 VB6 程序创建的随机访问文件。 向后兼容性对于新的 VB.net 程序至关重要。 有数千个已编写的文件需要访问。当我在记事本++中打开它们时,每个文件都有五行,尽管我无法在记事本++中区分随机字符的头部或尾部。这些文件应该包含四个记录,所以我不确定第五行的用途。
我可以访问这两个程序的旧源代码。下面是VB6的读写方法。
VB6编写方法
Dim fi as long
fi = FreeFile
Open fileName For Random As #fi Len = 32000
Put #fi, 1, Loads
Put #fi, 2, Nodes
Put #fi, 3, Names
Put #fi, 4, Options
Close fi
VB6读取方法
Dim fi As Long
fi = FreeFile
Open fileName For Random As #fi Len = 32000
Get #fi, 1, Loads
Get #fi, 2, Nodes
Get #fi, 3, Names
Get #fi, 4, Options
Close fi
VB,net读取方法(尝试)
在 VB.net 中,我使用以下内容来尝试读取相同的文件。
Dim fi As Integer = FreeFile()
FileOpen(fi, fileName, OpenMode.Random, RecordLength:=32000)
FileGet(fi, Loads, 1)
FileGet(fi, Nodes, 2)
FileGet(fi, Names, 3)
FileGet(fi, Options, 4)
FileClose(fi)
负载、节点、名称和选项在 VB6 中是[用户定义]类型,在 VB.net 中是结构。这些结构内部通常还有其他结构,而这些结构又包含更多结构。层次结构中的某些结构包含其他结构的数组,这些结构内部可能包含更多结构的数组。大多数结构字段都是单值或布尔值。 VB6 中有一些长整型,我在 VB.net 中将其转换为整数(以保持字节大小相同)。还有一些字符串字段。
当我尝试使用上面的 VB.net 读取方法时,它会获取负载、节点和名称的值。在
FileGet(fi, Options, 4)
行上,我得到: Systems.IO.EndOfStreamException: '无法读取超出流末尾的内容。'
看看上面的两种方法,它们的作用不应该是一样的吗?到底是什么原因导致 vb.net 中出现此异常?记录大小不是<= 32,000 bytes?
编辑
Options 基于typOptions,它使用typDesign 和typGeometry。 VB6:
Public Const numDebug = 12
Public Type typOptions
optDesign As typDesign
optDebug(numDebug) As Boolean
optGeom As typGeometry
optFrac As Single
End Type
Public Type typDesign
mem01 As Single
mem02 As Single
mem03 As Single
mem04 (3) As Single
End Type
Public Type typGeometry
member1 As Single
member2 As Single
member3 As Single
member4 As Single
member5 As Single
member6 As Single
member7 As Single
End Type
VB.net
Public Const numDebug = 12
Public Structure typOptions
Public optDesign As typDesign
Public optDebug() As Boolean
Public optGeom As typGeometry
Public optFrac As Single
End Structure
Public Structure typDesign
Public mem01 As Single
Public mem02 As Single
Public mem03 As Single
Public mem04 () As Single
End Structure
Public Structure typGeometry
Public member1 As Single
Public member2 As Single
Public member3 As Single
Public member4 As Single
Public member5 As Single
Public member6 As Single
Public member7 As Single
End Structure
' Elsewhere, when the form is loading:
ReDim Options.optDesign.mem04 (3)
ReDim Options.optDebug(numDebug)
编辑2
这些文件的文件大小似乎一致为 96,124 字节。选项仅存储 124 个字节,而不是 32,000 个。我尝试使用十六进制编辑器并添加“00”,直到有 128,000 字节(每条记录 32,000 字节 * 4 条记录),但随后我仍然遇到 无法读取超出流末尾的内容 异常。不过 128,000 字节的文件在 VB6 中确实可以工作。
我从 vbmigration.com 找到了一些关于此的信息:
基于此,我本以为将文件设置为 128,000 字节而不是 96,124 可以修复无法读取超出流末尾的异常。VB6 和 VB.NET 在 UDT(VB.NET 用语中的结构)方式上有很大不同 从文件中读取或写入文件。不仅结构元素以不同的格式存储到文件中,而且两种语言还以不同的方式管理文件结束条件。在 VB6 中,即使操作会将文件指针移动到当前文件的长度之外,您也可以读取 UDT;在 VB.NET 中这样的操作会导致异常。
我认为最好的方法是在数组成员上使用
VBFixedArray
属性。旧版二进制文件处理理解此属性,然后它应该正确读取文件。 (还有一个
VBFixedString
属性,用于描述 VBA
Type
中的固定长度字符串。)结果会是这样的:
Public Structure typDesign
Public mem01 As Single
Public mem02 As Single
Public mem03 As Single
<VBFixedArray(3)>
Public mem04() As Single
End Structure
您可以在此处找到该属性的 .NET 6 文档:
https://learn.microsoft.com/en-us/dotnet/api/microsoft.visualbasic.vbfixedarrayattribute?view=net-6.0
在FileSystem
命名空间中的
Microsoft.VisualBasic
类的文档中还对旧版二进制文件格式进行了一些讨论。
x(3) As Single
可以是
x1 As Single
、
x2 As Single
等。相反,类型中的
x() As Single
是一个 SafeArray,仅占用描述符使用的 4 个字节。