protobuf-net从磁盘读取对象流

4
考虑到我有非常大的对象集合(数百万个),这些对象是根据协议缠绕格式序列化的。 是否可以从文件流式传输这些项? 我尝试将对象序列化为 List<T>,然后反序列化单个 T 项,但最终只读取了流中的最后一项。 我还尝试了将每个实例单独序列化到流中,具有相同的效果,即在反序列化时仅读取最后一项。
我怀疑解决方案需要我知道每个序列化项的大小,然后从流中读取该大小,并将那段字节传递给protobuf解析器进行反序列化。 我想确保没有更容易的机制,不需要了解每个单独项目的长度(可能对于对象的每个实例都不同)来完成此任务。
我想到的另一个想法是将每个即将到来的对象的大小作为它自己在流中的一个对象包含在内,例如:
0: 第一个对象的元数据信息,包括类型/字节长度 1: 在0中定义的对象 2: 第二个对象的元数据信息,包括类型/字节长度 3: 在2中定义的对象 4: ...等等
版本信息: 我目前使用的是dotnet core 3.1和protobuf-net版本2.4.4
1个回答

3
在protobuf中,默认情况下,根对象不会被终止,旨在允许"合并" === "追加"。这与您所描述的非常常见的场景相冲突。幸运的是,许多库提供了一种机制,在对象之前编码长度,以解决此问题。您需要寻找的是 SerializeWithLengthPrefixDeserializeWithLengthPrefix 方法。
如果数据已存在为平面追加方式,并且无法重写:仍然有方法可以通过使用reader API来恢复它。这可能会更加复杂,但在必要时我曾经为人们恢复过这样的数据。

作为更新,对于那些来到这里的人,这个方法完全按照广告所说的工作。使用 SerializeWithLengthPrefix,您可以将一个项目序列化到流中,然后使用 DeserializeWithLengthPrefix 逐个读取项目。我能够使用这些和 IAsyncEnumerable<T> 实现从包含大量项目的文件异步读取。感谢 @Marc -- 此外,在我的情况下,我能够将所有内容读入列表,并重新编写文件以支持上述流式传输。 - mhand

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接