【问题标题】:How can I deserialize a MemoryStream to an array of Structs如何将 MemoryStream 反序列化为结构数组
【发布时间】:2017-06-22 21:36:46
【问题描述】:

我有一个结构(人)数组,我将其序列化并格式化如下

  <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

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

【问题讨论】:

  • 我是否给了你适当的信任(投票?)以获得一个很好的答案?我采纳了你的所有建议,改变了我的方法,一切都如你所说。非常感谢
  • 是的。接受答案(复选标记)是您所能做的,直到您获得更多代表。然后,您可以为任何您认为有帮助的帖子点赞。

标签: .net vb.net serialization binaryformatter


【解决方案1】:

您的处理方式有相当大的错误。从根本上说,您可以而且应该一次序列化和反序列化整个集合。您不能逐项遍历内存流,因为您不(不能)知道每条记录的序列化大小。但还有更多……

使用类而不是结构

MSDN 有一篇很好的文章,关于何时以及为什么使用Class 而不是Structure。见Choosing Between Class and Struct

使用列表而不是数组

数组很难处理,因为您现在需要所需的大小。尤其是使用硬编码的幻数,如果学生人数减少(或增加),您不希望必须重写应用程序来更改 35

List(Of T) 会根据需要增长。

不要使用 GetBuffer

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

但你甚至不需要MemoryStream...

使用文件流

您可以打开一个文件流并直接写入(或读取)该文件,而不是只写入一个内存流:

我的班级:

<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() 覆盖是为了方便调试/演示。在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

我所有的学生都来回了:

之前
Ziggy F 2007 年 5 月 17 日
佐伊 P 2007 年 8 月 1 日
胡佛 M 2005 年 7 月 21 日

之后
Ziggy F 2007 年 5 月 17 日
佐伊 P 2007 年 8 月 1 日
胡佛 M 2005 年 7 月 21 日

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-05
    • 2012-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多