二进制格式化程序,设置位置以反序列化特定对象

时间:2013-08-22 13:50:53

标签: c# serialization stream deserialization filestream

我想问一下使用二进制格式化程序序列化/反序列化对象。好吧,我正在尝试反序列化FileStream中的对象,该对象包含许多已逐个序列化的对象。对象的大小太大而无法保存在进程内存中,这就是为什么我不将所有对象打包在一个如下:列表,因为它们在进程内存中太大所以我序列化了很多根据需要多次。用这种方式它不需要很多进程memmory因为我只是交替处理一个对象而不是所有对象。看看我的意思草图

<FileStream>
----Object 1-----Size = 100 Mb------index = 0
----Object 2-----Size = 100 Mb------index = 1
----Object 3-----Size = 100 Mb------index = 2
----Object 4-----Size = 100 Mb------index = 3
----Object 5-----Size = 100 Mb------index = 4
----Object 6-----Size = 100 Mb------index = 5
</FileStream>

序列化对象也成功了,现在我遇到了反序列化对象的问题。 这是问题所在: 在列表中,我们可以带一个带索引的项目。因此,如果我们想采用第五个索引,我们可以将其称为:

    List<object> list = new List<object>();
    list(0) = "object1";
    list(1) = "object2";
    list(2) = "object3";
    list(3) = "object4";
    list(4) = "object5";
    list(5) = "object6";
    object fifthIndex = list[5]; // here we can get item based index

现在问题是如何在具有二进制格式化程序的文件流中的六个反序列化对象上获得具有第五个索引的对象,就像 列表方法 一样。我知道在FileStream中有一个名为“FileStream.Position”的属性,但它不喜欢Index,当我反序列化/序列化一个对象时,它看起来像一个随机数。也许它会增加随机数。

实际上我已经成功了但是我打赌这不是最好的方式来看看我曾尝试过的代码:

object GetObjectStream(FileStream fs, int index)
{
    if (fs != null)
    {
        BinaryFormatter binaryformatter = new BinaryFormatter();
        bool isFinished = false; int count = 0;
        while (isFinished == false)
        {
            try
            {
                object objectdeserialized = binaryformatter.Deserialize(fs);
                if (count == index) return objectdeserialized;
                count++;
            }
            catch
            {
                isFinished = true;
                return null;
            }
        }
    }
    return null;
}

这些代码 “foreach ”每个已被序列化的对象然后反序列化每个对象。我打赌我的代码不是最好的方法,因为反序列化包含100 MB的对象可能需要很长时间,我甚至不知道除了索引之外的对象将被处理或不处理?我希望方法就像“序列化跳跃”。

如果我们可以解决这个问题,你的回答对我非常有帮助和有用。

先谢谢..

2 个答案:

答案 0 :(得分:1)

每个对象很可能需要不同的空间来序列化 - 数据包的方式不同,特别是对于字符串和数组这样的东西。基本上,为了有效地 (即每次都没有完整地读取每个对象),你可能想要:

  • 为每个对象添加所需的数据量,通过将其序列化为MemoryStream,存储.Length(任何方便的方式; 4字节的小端块就足够了),然后将您写入MemoryStream的数据复制到输出中;那么你可以跳过n次项目n次 - (读取4个字节作为int,跳过那么多字节)
  • 在单独的索引中,在序列化每个对象之前存储基本流的.Position;然后要读取第n个对象,使用索引查找所需位置,然后滚动到那里

实际上,你在这里很幸运:BinaryFormatter实际上没有被记录为可以安全地追加,但是当它发生时确实有点工作,你做得那么好 - 但是对于所有序列化格式都不是这样。

但就个人而言,我怀疑是否有一种可以在这里使用的不同设计。

答案 1 :(得分:0)

----Write objects to file---
1. Keep a Dictionary<KeyType, long> dict.  KeyType probably int if you key on an object number. 
2. open file FileX for output; FileX.position = 0 at this point.
3. For each object: 
         update dictionary(oject.key, fileX.Position)
         Serialize object to FileX (note: FileX.Position is updated by BinaryFormatter)
4. Close FileX. Save Dictionary (serialize to another file).

----Read Back Object---
Use Dictionary to get offset based on key of object you want:
     do FileX.Seek(offset, 0); formatter.deserialize(FileX) to get back the
object you wish.