【问题标题】:protobuf-net stream objects from diskprotobuf-net 从磁盘流对象
【发布时间】:2020-05-12 08:45:21
【问题描述】:

考虑一下我有一个非常大的集合(数百万)根据原始线格式序列化的对象。是否可以从文件中流式传输这些项目?我尝试将对象序列化为List<T>,然后反序列化单个T 项目,但它最终只从流中读取最后一个项目。我还尝试将每个实例单独序列化到流中,其效果与反序列化时相同,它只读取最后一项。

我怀疑该解决方案需要我知道每个序列化项目的大小,然后从流中读取该大小并将该字节范围传递给 protobuf 序列化程序以进行反序列化。我想确保没有一种更简单的机制,不需要知道每个对象的每个实例的长度可能不同,来完成这项任务。

我的另一个想法是将每个即将到来的对象的大小作为它自己的对象包含在流中,例如:

0:第一个对象的元信息,包括类型/长度(以字节为单位) 1:定义在 0 中的对象 2:第二个对象的元信息,包括类型/长度(以字节为单位) 3:2中定义的对象 4:...等

版本信息: 我目前正在使用 dotnet core 3.1 和 protobuf-net 版本 2.4.4

【问题讨论】:

    标签: c# protocol-buffers protobuf-net


    【解决方案1】:

    在 protobuf 中,根对象默认不会终止,目的是允许“合并”===“追加”。这与您所描述的非常常见的情况相冲突。幸运的是,出于这个原因,许多库提供了一种机制来对对象之前的长度进行编码。您正在寻找的是 SerializeWithLengthPrefixDeserializeWithLengthPrefix 方法。

    如果数据已经以平面附加的形式存在,并且无法重写:仍然可以使用读取器 API 来恢复它。有点复杂,但我过去曾在需要时为人们恢复过此类数据。

    【讨论】:

    • 作为更新,对于那些发现自己在这里的人来说,这与宣传的完全一样。使用SerializeWithLengthPrefix,您可以一次将一项序列化为流,然后使用DeserializeWithLengthPrefix 一次读取一项。我能够使用这些和IAsyncEnumerable<T> 来实现从包含大量项目集合的文件中异步读取。谢谢@Marc——另外,就我而言,我能够以列表的形式读取所有内容并重写文件以支持上述流。
    猜你喜欢
    • 1970-01-01
    • 2011-09-11
    • 1970-01-01
    • 1970-01-01
    • 2012-09-19
    • 2011-02-12
    • 1970-01-01
    • 1970-01-01
    • 2017-10-19
    相关资源
    最近更新 更多