【问题标题】:Binary Formatter, Set Position to Deserialize Particular Object二进制格式化程序,设置位置以反序列化特定对象
【发布时间】:2013-08-25 07:10:38
【问题描述】:

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

<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

现在的问题是我怎样才能获得具有第五个索引的对象,就像 List Method 在具有二进制格式化程序的文件流中的六个反序列化对象上。我知道在 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 的对象可能需要很长时间,我什至不知道除了曾经被反序列化的索引之外的对象是否会被处理?我想要像 “序列化飞跃”这样的方法。

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

之前谢谢..

【问题讨论】:

  • 显示序列化列表的代码。
  • @DarinDimitrov 序列化列表对象,我的意思是:binaryformatter.Serialize(new List());假设 new List() 中有很多项目,然后我将其序列化。
  • 但是如果列表中有很多项目,它们如何适应内存?我认为这首先是你的问题 - 因为列表太大而内存不足。
  • List,这只是一个寓言,可以理解我根本不将对象写入List,而是我一个一个地序列化并在多次保存在文件中后处理对象。比喻,我怎样才能像 List 我所说的索引一样选择项目。但这是一个反序列化流
  • 所以你要追加到现有文件?

标签: c# serialization stream deserialization filestream


【解决方案1】:
----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.

   

【讨论】:

    【解决方案2】:

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

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

    实际上,你在这里很幸运:BinaryFormatter 实际上并没有记录为可以安全附加,但碰巧它确实有点工作,你这样做 - 但这不是并非所有序列化格式都如此。

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

    【讨论】:

    • 好的,我明白了。使用您的第二个解决方案,现在的问题是,在序列化我拥有的所有对象之后,我们得到了所有 index/position length。好吧,现在我如何将 "Index/Position" 放在文件的标题中,而我们已经完成了 6 次序列化。我如何将位置设置为 0 以在序列化流出现错误时序列化标头,因为位置不整洁。
    • @Rizky 你不能在事后神奇地将东西移动到文件的“标题”;首先,这需要您移动所有其余数据,其次:更改偏移量 - 尽管为此,您可能可以只是通过将所有内容抵消标题的大小来作弊。但是那时你已经让事情从根本上不可附加,因此我使用了“分离”这个词,这将允许你继续以你的方式使用它。如果你想要一个文件,并且你希望它是可附加的,你需要使用第一种方法,或者不同的序列化器。/
    • 我听从了你的建议,成功了..!我读回你的建议,这是使用 MemoryStream 然后复制数据的内容和索引位置,这很好!我非常感谢你,但这仍然不能解决我的其他问题。现在回到我的问题:我需要对每个对象最多 100 MB 的数据进行序列化。有了这个大小,即使我需要序列化 ​​20 个对象,我也需要在 memorystream 中一次处理它们,进程内存中的大小将达到 2 GB!这会导致程序崩溃,当然这个问题是相当困难的。
    • 实际上是否可附加输出对我来说并不重要,我只需要将我的资源放在一个文件中,然后在运行时将其加载回某些对象(根据程序的状态)。因此,为什么我需要按索引反序列化对象。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-11-30
    • 2023-03-04
    • 2020-08-24
    • 2014-01-04
    • 1970-01-01
    • 2013-08-02
    • 1970-01-01
    相关资源
    最近更新 更多