65.9K
CodeProject 正在变化。 阅读更多。
Home

对象 - 集合 - 二进制文件: 使用序列化和反序列化处理基于集合的二进制文件

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.20/5 (4投票s)

2008年11月20日

Ms-PL

4分钟阅读

viewsIcon

35974

downloadIcon

259

在本教程中,我们将仔细研究一种技术,该技术可以轻松地将对象外部存储,轻松检索它们,并像处理某种简单数据库一样处理它们。

引言

构建处理结构化数据但不使用 SQL Server 等经典数据库的应用程序的最流行方法是使用 XML。基本上,XML 做得非常好,如果您熟悉 .NET 中的 XML,您可以使用一套强大的函数来处理存储的数据。

但还有更多。

使用代码

在本教程中,我们将仔细研究一种技术,该技术可以轻松地将对象外部存储,轻松检索它们,并像处理某种简单数据库一样处理它们。

我们只需要四种要素来构建我们的系统

  1. 我们可以从中实例化对象的类。
  2. 某种集合可以将这些对象推入其中——在我们的例子中是哈希表。
  3. 一个二进制写入器,用于实际将我们的数据包保存到磁盘。
  4. 一个二进制读取器,用于检索我们的数据。

这听起来可能比实际上更令人困惑,所以我们最好直接开始,看一个基本示例。

让我们启动 VS 2005 并使用 VB.NET 创建一个新的命令行应用程序。将初始模块从“Module1”重命名为“Binarywriter”并将项目保存到合适的位置。现在我们可以开始仔细研究我们的主题了。

  1. 数据类:首先,我们添加一个名为“cItem”[1]的新类并为其提供一个属性。
  2. Public Class cItem
    
        Private _dValue As Double
    
        Public Property Value()
            Get
                Return _ dValue
            End Get
            Set(ByVal Value)
                _ dValue = (Value * 1000)
            End Set
        End Property
    End Class

    稍后我们将从这个类派生对象并将它们存储在我们的集合中,以便立即将它们保存到二进制文件中。

  3. 集合:为了满足第二个要求,我们切换回“BinaryWriter”模块并添加一些 Imports 语句。具体来说,是
  4. Imports System.IO
    Imports System.Runtime.Serialization.Formatters.Binary
    Imports System.Runtime.Serialization

    在此之后,我们添加一个名为“Serialize”的 Sub,在其中我们将用大量随机值填充我们的集合。单个值存储在我们的 cItem 类的对象实例中。

    Private Sub Serialize()
        'define our Collection – a hashtable in our case
        'because it will hold all the Items we are going to
        'create, we will call it ItemCollection
        Dim oItemCollection As New Hashtable
    
        Dim oItem As cItem
        Dim iCounter As Integer
    
        'We will fill our Data-File with a mass of values
        For iCounter = 1 To 10000
            'Make new Item from cItems
            oItem = New cItem
            Randomize()
            'Give it a random Value
            oItem.Value = Rnd()
            'Add it to our collection
            oItemCollection.Add("Value" & iCounter, oItem)
            'destroy our Item
            oItem = Nothing
        Next
    End Sub
  5. 二进制写入器:现在我们准备将填充的集合存储为二进制文件。为此,我们使用 FileStreamBinaryFormatter 将集合流式传输到磁盘。
  6. Private Sub Serialize()
        '(...)
    
        'As we want to write a binary file, we need to open a
        'FileStream to create one. That’s why we need the System.IO
        'Import for, btw.
        Dim oFileWriter As New FileStream("DataFile.dat", FileMode.Create)
    
    
        'Construct a BinaryFormatter and use it to serialize the data
        'to the stream. 
        Dim oFormatter As New BinaryFormatter
        Try
            oFormatter.Serialize(oFileWriter, oItemCollection)
        Catch e As SerializationException
            Console.WriteLine("Serialization failed. Reason: " & e.Message)
            Throw
        Finally
            oFileWriter.Close()
        End Try
    End Sub
  7. 二进制读取器:为了从数据文件中检索回我们的数据,我们利用反序列化。为此,我们向 BinaryFile 模块添加一个新函数,并将其命名为“Deserialize”。为了保存检索到的数据,我们初始化一个空的哈希表。在此之后,我们将以与存储集合到二进制文件相同的方式进行,并使用 FileStreamBinaryFormatter 来实际访问数据。在对数据文件的反序列化内容进行类型转换后,我们就完成了。
  8. Private Sub Deserialize()
        Dim oItemCollection As Hashtable
        Dim oFileReader As FileStream
        Dim oFormatter As BinaryFormatter
    
        'Define our Collection. Corresponting to the Collection used
        'in the Serialize() –Function it’s a hashtable here.
        oItemCollection = New Hashtable
        oItemCollection = Nothing
    
        'We want to read from our binary file, so we initialize
        'a Filestream
        oFileReader = New FileStream("DataFile.dat", FileMode.Open)
    
        Try
            oFormatter = New BinaryFormatter
    
            oItemCollection = _
              DirectCast(oFormatter.Deserialize(oFileReader), Hashtable)
        Catch e As SerializationException
            Console.WriteLine("Deserialize failed. Reason: " & e.Message)
            Throw
        Finally
            oFileReader.Close()
        End Try
    End Sub

现在我们的数据已经检索回哈希表中。

后续步骤:引言中提到,可以像处理某种简单数据库一样处理二进制文件。毫无疑问,这是一个真实的陈述,但稍微不准确的表述,因为——您可能已经注意到——我们不是直接处理数据文件,而是对内存中的集合执行操作。

这又是一个巨大的优势,因为您可以针对特定需求优化您的集合。

但是,让我们看两个基本示例,说明如何使用我们上面设计的系统并访问一些数据。

访问值

在这种情况下,您可以使用 DictionaryEntry 并将条目 DirectCastcItem 类,以便访问对象的实际值。

Dim oEntry As DictionaryEntry
Dim iCounter As Integer = 0
Dim iValue As Integer

For Each oEntry In oItemCollection
    iValue = DirectCast(oEntry.Value, cItem).Value

    If iValue = iRandomNumber Then
        iCounter += 1
    End If
Next

Console.WriteLine("The value {0} was found {1} times", _
                  iRandomNumber, iCounter)

结果:本教程演示了如何使用集合派生类和(反)序列化轻松地将数据存储到/从二进制文件中检索。

与经典数据库相比,将对象保留在集合中并对其进行序列化提供了一些优势,前提是数据量没有过大。这些优势包括数据文件以二进制格式存储,这显然限制了对数据文件的访问。此外,它使得处理结构化数据快速而方便,因为我们将所有数据加载到内存中,所以对数据的每个操作都是内存中的操作。

此外,还展示了检索二进制数据文件是多么容易。

通过精心选择的集合类型和设计良好的数据类,您可以利用许多优势来编写简单、高效且清晰的代码,从而可能产生一个健壮的应用程序。哈希表作为集合仅用于演示目的。基本上,您可以使用任何类型的集合(甚至您自己的)。与数据类结合使用,您拥有充足的工具来使您的应用程序正确处理二进制文件。

注意:不幸的是,上述方法不适用于 .NET Compact Framework,因此您不能使用此方法在移动设备中存储数据。

[1] 我知道很多人会说“cItem”不符合 .NET 的常规命名约定。我不会对此表示异议,但我在这里做的是遵循我公司的命名约定。这不仅仅因为我是作者;)

© . All rights reserved.