protobuf 可以部分读取吗?

Posted

技术标签:

【中文标题】protobuf 可以部分读取吗?【英文标题】:Can protobuf read partially? 【发布时间】:2013-02-15 16:57:05 【问题描述】:

我想将我的地形数据保存到一个文件中并仅加载其中的一部分,因为它太大而无法将其作为一个整体存储在内存中。其实我什至不知道protobuf是否适合这个目的。

例如,我会有这样的结构(可能在语法上无效,我只知道简单的基础知识):

message Quad 
    required int32 x = 1;
    required int32 z = 2;

    repeated int32 y = 3;

xz 值在我的程序中可用,通过使用它们,我想找到具有相同 x的正确 Quad 对象> 和 z(在文件中)来获取 y 值。但是,我不能只用 ParseFromIstream() 解析文件,因为(我认为是这样)它将整个文件加载到内存中,但在我的情况下,文件太大了。

那么,protobuf 是否能够加载一个对象,发送给我检查,如果对象错误,给我第二个?

实际上...我只想问:ParseFromIstream() 是否会将整个文件加载到内存中?

【问题讨论】:

@infact 这是一个荒谬的评论,没有某种形式的限定,即你觉得它失败的地方。 【参考方案1】:

虽然有些库允许您部分读取文件,但 Google 推荐的技术是让文件包含多条消息:

https://developers.google.com/protocol-buffers/docs/techniques

协议缓冲区不是为处理大消息而设计的。作为一般经验法则,如果 您正在处理每条大于 1 兆字节的消息,可能是时候考虑 替代策略。

也就是说,Protocol Buffers 非常适合处理大数据中的单个消息 放。通常,大型数据集实际上只是小片段的集合,其中每个小片段 片段可能是结构化的数据片段。

因此,您可以将一长串Quad 消息写入文件,由消息的长度分隔。如果您需要随机寻找特定的Quads,您可能需要添加某种索引。

【讨论】:

【参考方案2】:

这取决于您使用的实现。有些具有“按序列读取”的 API。例如,假设您将其存储为“重复的 Quad”,那么使用 protobuf-net 将是:

int x = ..., y = ...;
var found = Serializer.DeserializeItems<Quad>(source)
            .Where(q => q.x ==x && q.y == y);

关键是:它产生一个假脱机(不是一次全部加载)和短路序列。

我不知道具体的 c++ api,但我希望它有类似的东西 - 但最坏的情况是你可以解析 varint 标头并准备一个长度上限的流。

【讨论】:

嘿,我目前正在阅读您的一些其他答案,我认为这些答案与我的问题相似,但我想知道使用 protobuf 对我来说是否合理。现在我将数据作为纯文本“[x z] y y y y .....”并在下一行再次 [x1 z1] y1 y1 y1 y1... 等等。protobuf 序列化是否会使文件更小在这种情况下? 哦,我找到了很好的答案***.com/questions/7174635/… y 值范围从 0 到 255(其中很多将在 ~127 左右),所以看起来它可以很好地压缩它。跨度>

以上是关于protobuf 可以部分读取吗?的主要内容,如果未能解决你的问题,请参考以下文章

我们可以更改钴的 protobuf 版本吗?

Jmeter protobuf 测试。无法读取 Protobuf 消息

php protobuf不能为null吗

protobuf-net 子消息未正确读取

protobuf-net:日期时间的编码

如何使用 Python protobuf 读取二进制 C++ protobuf 数据?