0

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

<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中,我们可以获取一个带有索引的项目。因此,如果我们想采用第五个索引,我们可以将其称为:

    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”的属性,但它不喜欢索引,当我反序列化/序列化对象时它看起来像一个随机数。也许它会增加随机数。

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

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 的对象可能需要很长时间,我什至不知道除了曾经被反序列化的索引之外的对象是否会被处理?我想要像“序列化飞跃”一样的方法。

如果我们能解决这个问题,你的回答对我很有帮助。

之前谢谢。。

4

2 回答 2

1

每个对象很可能会占用不同数量的空间来序列化 - 数据包不同,特别是对于字符串和数组之类的东西。基本上,要有效地做到这一点(即每次不完整读取每个对象),您可能希望:

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

实际上,您在这里很幸运:BinaryFormatter实际上并没有记录为可以安全附加,但是碰巧它确实可以解决问题-但并非所有序列化格式都如此。

不过,就个人而言,我会质疑这里是否可以使用不同的设计。

于 2013-08-22T14:38:02.500 回答
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.

   
于 2020-08-31T10:29:40.477 回答