使用C++逐步向文件中写入Protobuf。

3

我有以下protobuf:

message FrameData {
    ... arbitrarily complex ...
}

message DataDump {
  optional uint64 headerField1 = 1;
  optional uint64 headerField2 = 2;
  optional uint64 headerField3 = 3;
  repeated FrameData frameData = 4;
}

我正在逐个创建frameData protobufs,并希望将DataDump protobuf写入文件。我可以通过构建DataDump protobuf并调用SerializeToOstream来完成这一操作,但问题是数据量达到了几百GB,这种方式需要先在内存中构建所有数据才能将其转储到磁盘上。
由于重复字段frameData是protobuf中的最后一个字段,我认为可以先将头部写入文件,然后在生成每个FrameData protobuf后迭代地流出frameData元素。
如何实现这一点?
1个回答

1

Protobuf消息(特别是proto2语法消息)可以连接以合并它们的内容。要弄清楚它的工作原理,需要阅读protobuf编码格式文档

在您的情况下,您可以先将带有标题字段的DataDump消息写入文件中。之后,放入任意数量的frameData项,并将该消息附加到文件末尾。重复此操作直到写入所有项为止。

当解码器读取消息时,所有项似乎都是大型frameData数组的一部分。


然而,这可能会成为解码方面的问题:在许多实现中,这迫使您一次性将整个文件读入内存,而不是以较小的块进行处理。
特别是如果您需要随机访问和某种索引,存储数百GB数据集可能会受益于更高级的存储格式。

我应该如何做到这一点?只需先使用SerializeToOstream将DataDump序列化到文件流中,然后再使用相同的文件流将每个FrameData进行序列化吗?这个问题似乎表明,这样做只会保留最后一个消息。对于读取操作,我不需要对元素进行随机访问,只需要按顺序读取即可。是否有类似的方法可以实现呢? - undefined
@user1282931 这个问题只有可选/必填字段。因为它们只能包含一个值(不像重复字段那样),新值会覆盖旧值。但是,如果你想要以较小的块进行顺序访问,使用一个将块分隔开的格式是一个好主意。例如,writeDelimitedTo() - undefined
writeDelimitedTo似乎是c# API的一个方法。在c++中有相应的等价物吗? - undefined
好的,我找到了。虽然API文档中没有记录,但是在https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/util/delimited_message_util.h中有相关内容,通过使用这个工具,我能够按顺序将消息进行序列化和反序列化。太棒了!:) - undefined

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