use*_*169 10 serialization protobuf-net
我有一个约5亿件物品的清单.如果我序列化单个项目而不是列表,我可以将它序列化为带有protobuf-net文件的文件 - 我无法将项目收集到价格列表中,然后序列化,因为我的内存不足.所以,我必须一次序列化一条记录:
using (var input = File.OpenText("..."))
using (var output = new FileStream("...", FileMode.Create, FileAccess.Write))
{
string line = "";
while ((line = input.ReadLine()) != null)
{
Price price = new Price();
(code that parses input into a Price record)
Serializer.Serialize(output, price);
}
}
Run Code Online (Sandbox Code Playgroud)
我的问题是关于反序列化的部分.似乎Deserialize方法不会将流的位置移动到下一条记录.我试过了:
using (var input = new FileStream("...", FileMode.Open, FileAccess.Read))
{
Price price = null;
while ((price = Serializer.Deserialize<Price>(input)) != null)
{
}
}
Run Code Online (Sandbox Code Playgroud)
我看到一个真实的价格记录,然后其余的是空记录 - 我得到Price对象,但所有字段都被初始化为默认值.
如何正确反序列化包含未序列化为列表的对象列表的流?
好消息!protobuf-net API 正是针对这种情况设置的。您应该会看到 SerializeItems 和 DeserializeItems 对使用的方法IEnumerable<T>,允许流入和流出。向它提供枚举的最简单方法是通过源数据上的“迭代器块”。
如果,无论出于何种原因,这不方便,则与在每个项目的基础上使用 SerializeWithLengthPrefix 和 DeserializeWithLengthPrefix 100% 相同,指定(作为参数)字段:1 和前缀样式:base-128。您甚至可以使用 SerializeWithLengthPrefix 进行写入,使用 DeserializeItems 进行读取(只要您使用字段 1 和 base-128)。
重新示例 - id 必须在完全可重现的场景中看到它才能发表评论;实际上,我希望您只返回一个对象,其中包含来自每个对象的组合值 - 因为没有长度前缀,protobuf 规范假设您只是将值连接到单个对象。上面提到的两种方法避免了这个问题。