我有一个Structure(Person)数组,我将其序列化并格式化如下
<Serializable()> Structure Person
Public strID As String
Public strName As String
Public strReport As String
Public strAttend As String
Public Shared Widening Operator CType(v As Person) As IO.MemoryStream
Try
Throw New NotImplementedException()
Catch ex As Exception
MsgBox("Failed to deserialise." + Chr(13) + "Reason: " & ex.Message)
End Try
End Operator
End Structure
Public Student(35) As Person
Dim bf As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter()
Dim ms as New System.IO.MemorySteam()
bf.Serialize(ms,Student(count))
My.Computer.FileSystem.WriteAllBytes(strFile1,ms.GetBuffer(),True)
根据需要创建并填充文件。当我用写字板检查时,所有记录都存在。 当我反序列化它时,如下所示,我只看到重复的第一条记录。我想是指针没有移动,或者我在每次迭代时都要回到记录1。我错过了什么?
Public Student(35) As Person
Dim bf As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter()
Dim ms as New System.IO.MemorySteam()
Dim bytes As Byte() = My.Computer.FileSystem.ReadAllBytes(strFile1)
My.Computer.FileSystem.ReadAllBytes(strFile1)
Student(35) = DirectCast(bf.Deserialize(New MemoryStream(bytes)),Person)
ms.Seek(0,SeekOrigin.Begin)
For i = 0 to 19
Student(i) = DirectCast(bf.Deserialize(New MemoryStream(bytes)),Person)
Next
提前感谢您提供的任何帮助或建议。
答案 0 :(得分:2)
你的方式有很多错误。从根本上说,您可以并且应该立即对整个集合进行序列化和反序列化。你不能逐项逐步通过内存流,因为你不能(不能)知道每条记录的序列化大小。但还有更多......
MSDN在使用Class
而不是Structure
的时间和原因方面有一篇很好的文章。见Choosing Between Class and Struct
阵列很结实,很难处理,因为你需要现在所需的大小。特别是对于硬编码的魔术数字,如果学生数量减少(或增长),您可能不希望重写应用程序以在任何地方更改35
。
根据需要增加List(Of T)
。
MemoryStream
使用的内部缓冲区会根据需要自行增长。但它通过每次加倍缓冲区大小来实现。这意味着几乎一半的缓冲区可能是未使用的空间。使用.ToArray()
获取已使用的部分。请参阅MemoryStream.GetBuffer Method - 阅读备注部分。
但你甚至不需要MemoryStream
......
您可以打开文件流并直接写入(或读取)到该文件流,而不是写入memstream只写一个文件:
我的班级:
<Serializable()>
Public Class Student
Public Property Name As String
Public Property Gender As String
Public Property EnrollDate As Date
Public Property FavoriteColor As String
Public Sub New()
End Sub
Public Sub New(n As String)
Name = n
End Sub
Public Overrides Function ToString() As String
Return Name & " " & EnrollDate
End Function
End Class
ToString()
覆盖是为了方便调试/演示。在Student
中创建List(Of T)
对象的集合:
Dim Students As New List(Of Student)()
Dim s As Student
s = New Student("Ziggy F")
s.EnrollDate = #5/17/2007#
s.Gender = "M"
s.FavoriteColor = "Orange"
Students.Add(s)
... etc
Console.WriteLine("BEFORE")
For Each s In Students
Console.WriteLine(s)
Next
序列化:
Dim filename As String = "C:\Temp\myStudents.dat"
Using fs As New FileStream(filename, FileMode.Create)
Dim bf As New BinaryFormatter
bf.Serialize(fs, Students)
End Using
反序列化并测试:
Dim newStudents As List(Of Student)
' to do check if exists
Using fs As New FileStream(filename, FileMode.Open)
Dim bf As New BinaryFormatter
newStudents = DirectCast(bf.Deserialize(fs), List(Of Student))
End Using
Console.WriteLine("AFTER")
For Each s In newStudents
Console.WriteLine(s)
Next
我所有的学生都往返了:
在
Ziggy F 5/17/2007
Zoey P 8/1/2007
胡佛M 7/21/2005在
Ziggy F 5/17/2007
Zoey P 8/1/2007
胡佛M 7/21/2005