如何将 MemoryStream 反序列化为 Structs 数组
How can I deserialize a MemoryStream to an array of Structs
我有一个 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
提前感谢您提供的任何帮助或建议。
您的处理方式有很多错误。从根本上说,您可以而且应该立即序列化和反序列化整个集合。您不能逐项遍历内存流,因为您不知道(不能)知道每条记录的序列化大小。但还有更多...
使用 Class 而不是结构
MSDN 上有一篇很好的文章,介绍何时以及为何使用 Class
而不是 Structure
。参见 Choosing Between Class and Struct
使用列表而不是数组
数组很难处理,因为您现在需要达到所需的大小。特别是对于硬编码的幻数,如果学生人数减少(或增加),您将不希望必须重写应用程序以更改 35
所有地方。
A List(Of T)
根据需要增长。
不要使用 GetBuffer
MemoryStream
使用的内部缓冲区会根据需要自行增长。但它通过每次 双倍 缓冲区大小来实现。这意味着几乎一半的缓冲区可能未被使用 space。使用 .ToArray()
获取使用的部分。请参阅 MemoryStream.GetBuffer Method - 阅读备注部分。
但你甚至不需要 MemoryStream
...
使用文件流
与其写入 memstream 只是为了将其写入文件,您可以打开文件流并直接写入(或读取)它:
我的Class:
<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()
覆盖是为了方便 debugging/demo。在 List(Of T)
:
中创建 Student
对象的集合
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
我所有的学生都完成了往返:
BEFORE
Ziggy F 5/17/2007
Zoey P 8/1/2007
Hoover M 7/21/2005
AFTER
Ziggy F 5/17/2007
Zoey P 8/1/2007
Hoover M 7/21/2005
另请参阅:
我有一个 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
提前感谢您提供的任何帮助或建议。
您的处理方式有很多错误。从根本上说,您可以而且应该立即序列化和反序列化整个集合。您不能逐项遍历内存流,因为您不知道(不能)知道每条记录的序列化大小。但还有更多...
使用 Class 而不是结构
MSDN 上有一篇很好的文章,介绍何时以及为何使用 Class
而不是 Structure
。参见 Choosing Between Class and Struct
使用列表而不是数组
数组很难处理,因为您现在需要达到所需的大小。特别是对于硬编码的幻数,如果学生人数减少(或增加),您将不希望必须重写应用程序以更改 35
所有地方。
A List(Of T)
根据需要增长。
不要使用 GetBuffer
MemoryStream
使用的内部缓冲区会根据需要自行增长。但它通过每次 双倍 缓冲区大小来实现。这意味着几乎一半的缓冲区可能未被使用 space。使用 .ToArray()
获取使用的部分。请参阅 MemoryStream.GetBuffer Method - 阅读备注部分。
但你甚至不需要 MemoryStream
...
使用文件流
与其写入 memstream 只是为了将其写入文件,您可以打开文件流并直接写入(或读取)它:
我的Class:
<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()
覆盖是为了方便 debugging/demo。在 List(Of T)
:
Student
对象的集合
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
我所有的学生都完成了往返:
BEFORE
Ziggy F 5/17/2007
Zoey P 8/1/2007
Hoover M 7/21/2005AFTER
Ziggy F 5/17/2007
Zoey P 8/1/2007
Hoover M 7/21/2005
另请参阅: