VB6转.NET:多应用间自定义结构数组的跨程序序列化替代方案咨询
寻求.NET中跨应用的自定义结构数组文件存读的现代实现方案
我正在开发一款应用,使用包含多个变量及其他自定义结构子数组的自定义结构数组存储数据,需要实现该数据的文件存读功能。此前使用BinaryFormatter序列化方案时,在多个应用间加载保存的文件会出现问题,因此改用了VB6风格的FilePut/FileGet技术实现目标,现咨询是否有更现代的.NET代码写法。
当前使用的VB6风格实现代码
保存代码
'// Get file number Dim fn As Integer = FreeFile() '// Opens the file for binary write FileOpen(fn, FileName, OpenMode.Binary, OpenAccess.Write) '// Get persons count Dim pc As Integer = Persons.GetUpperBound(0) '// Write persons count FilePut(fn, pc) '// Write Persons FilePut(fn, Persons) '// Close the file FileClose(fn)
加载代码
'// Get file number Dim fn As Integer = FreeFile() '// Opens the file for binary read FileOpen(fn, FileName, OpenMode.Binary, OpenAccess.Read) '// Get persons count Dim pc As Integer '// Read persons count FileGet(fn, pc) '// Prepare Persons array for it Persons = Nothing ReDim Persons(0 To pc) '// Read Persons FileGet(fn, Persons) '// Close the file FileClose(fn)
此前序列化方案的问题详情
测试用的两个应用StructureSaver_App_A和StructureSaver_App_B代码完全一致,但跨应用加载时报错:
- 在App_A保存的文件,App_B加载时提示:
System.Runtime.Serialization.SerializationException: 'Unable to find assembly 'StructureSaver_App_A, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.' - 在App_B保存的文件,App_A加载时提示:
System.Runtime.Serialization.SerializationException: 'Unable to find assembly 'StructureSaver_App_B, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.'
同一应用内存读正常,以下是当时使用的序列化代码:
结构定义
'// Parent structure <Serializable> Private Structure Parents Dim Name As String Dim Age As Integer Dim Kids() As Kids End Structure '// Kid structure <Serializable> Private Structure Kids Dim Name As String Dim Age As Integer Dim GoesInScool As Boolean End Structure Private Persons() As Parents
保存代码
'// Gets BinaryFormatter Dim BF As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter() '// Makes new Memorystream Dim MS As New System.IO.MemoryStream() '// Serialize to Memorystream BF.Serialize(MS, Persons) '// Writes the content to file My.Computer.FileSystem.WriteAllBytes(FileName, MS.GetBuffer(), False)
加载代码
'// Loads file to a byte() Dim bytes As Byte() = My.Computer.FileSystem.ReadAllBytes(FileName) '// Gets BinaryFormatter Dim BF As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter() '// Reads data Persons = DirectCast(BF.Deserialize(New System.IO.MemoryStream(bytes)), Parents())
现代.NET替代方案
方案1:使用System.Text.Json(跨平台、无依赖)
Json是文本格式,可读性好,跨应用兼容性强,无需关心程序集信息。
首先调整结构为可访问级别(Private结构无法被Json序列化,建议改为Public),可添加特性控制字段名:
Public Structure Kids <JsonPropertyName("name")> Public Name As String <JsonPropertyName("age")> Public Age As Integer <JsonPropertyName("goes_to_school")> Public GoesInScool As Boolean End Structure Public Structure Parents <JsonPropertyName("name")> Public Name As String <JsonPropertyName("age")> Public Age As Integer <JsonPropertyName("kids")> Public Kids() As Kids End Structure
保存代码
Dim jsonOptions As New JsonSerializerOptions With { .WriteIndented = True ' 可选,格式化输出便于阅读 } Dim jsonString As String = JsonSerializer.Serialize(Persons, jsonOptions) File.WriteAllText(FileName, jsonString)
加载代码
Dim jsonString As String = File.ReadAllText(FileName) Persons = JsonSerializer.Deserialize(Parents())(jsonString)
方案2:使用protobuf-net(二进制格式,高性能)
protobuf是二进制序列化格式,体积小、速度快,跨语言跨应用兼容性好。
首先安装NuGet包protobuf-net,给结构添加序列化特性:
<ProtoContract> Public Structure Kids <ProtoMember(1)> Public Name As String <ProtoMember(2)> Public Age As Integer <ProtoMember(3)> Public GoesInScool As Boolean End Structure <ProtoContract> Public Structure Parents <ProtoMember(1)> Public Name As String <ProtoMember(2)> Public Age As Integer <ProtoMember(3)> Public Kids() As Kids End Structure
保存代码
Using fs As New FileStream(FileName, FileMode.Create) Serializer.Serialize(fs, Persons) End Using
加载代码
Using fs As New FileStream(FileName, FileMode.Open) Persons = Serializer.Deserialize(Parents())(fs) End Using
方案3:手动二进制序列化(自定义格式,完全可控)
如果需要保持二进制格式且完全自定义,可以手动写入/读取每个字段,避免依赖旧API:
保存代码
Using writer As New BinaryWriter(File.Open(FileName, FileMode.Create)) ' 写入人员数量 writer.Write(Persons.Length) For Each parent In Persons ' 写入Parent字段 writer.Write(parent.Name) writer.Write(parent.Age) ' 写入子数组长度 writer.Write(parent.Kids.Length) For Each kid In parent.Kids writer.Write(kid.Name) writer.Write(kid.Age) writer.Write(kid.GoesInScool) Next Next End Using
加载代码
Using reader As New BinaryReader(File.Open(FileName, FileMode.Open)) Dim count As Integer = reader.ReadInt32() ReDim Persons(0 To count - 1) For i = 0 To count - 1 Dim parent As New Parents() parent.Name = reader.ReadString() parent.Age = reader.ReadInt32() Dim kidCount As Integer = reader.ReadInt32() ReDim parent.Kids(0 To kidCount - 1) For j = 0 To kidCount - 1 Dim kid As New Kids() kid.Name = reader.ReadString() kid.Age = reader.ReadInt32() kid.GoesInScool = reader.ReadBoolean() parent.Kids(j) = kid Next Persons(i) = parent Next End Using
内容的提问来源于stack exchange,提问作者dreasi0n
相关产品推荐
相关产品推荐

