如何将MemoryStream反序列化为Structs数组

时间:2017-06-22 21:36:47

标签: .net vb.net serialization binaryformatter

我有一个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

提前感谢您提供的任何帮助或建议。

1 个答案:

答案 0 :(得分:2)

你的方式有很多错误。从根本上说,您可以并且应该立即对整个集合进行序列化和反序列化。你不能逐项逐步通过内存流,因为你不能(不能)知道每条记录的序列化大小。但还有更多......

使用类而不是结构

MSDN在使用Class而不是Structure的时间和原因方面有一篇很好的文章。见Choosing Between Class and Struct

使用List而不是数组

阵列很结实,很难处理,因为你需要现在所需的大小。特别是对于硬编码的魔术数字,如果学生数量减少(或增长),您可能不希望重写应用程序以在任何地方更改35

根据需要增加List(Of T)

不要使用GetBuffer

MemoryStream使用的内部缓冲区会根据需要自行增长。但它通过每次加倍缓冲区大小来实现。这意味着几乎一半的缓冲区可能是未使用的空间。使用.ToArray()获取已使用的部分。请参阅MemoryStream.GetBuffer Method - 阅读备注部分。

但你甚至不需要MemoryStream ......

使用FileStream

您可以打开文件流并直接写入(或读取)到该文件流,而不是写入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

另请参阅:Beginner's Guide to Classes and Lists