谷歌协议缓冲区-将消息存储到文件中



我使用谷歌协议缓冲区来序列化股票市场数据(即时间戳、出价、询问字段)。我可以将一条消息存储到一个文件中,并对其进行反序列化而不会出现问题。

如何将多条消息存储在一个文件中?不知道如何将这些信息分开。我需要能够动态地将新消息附加到文件中。

我建议在Message对象上使用writeDelimitedTo(OutputStream)parseDelimitedFrom(InputStream)方法。writeDelimitedTo在消息本身之前写入消息的长度;CCD_ 5然后使用该长度只读取一条消息而不读取更多消息。这允许将多个消息写入单个OutputStream,然后分别进行解析。有关详细信息,请参阅https://developers.google.com/protocol-buffers/docs/reference/java/com/google/protobuf/MessageLite#writeDelimitedTo(java.io.OutputStream)

来自文档:

http://code.google.com/apis/protocolbuffers/docs/techniques.html#streaming

流式传输多条消息

如果要将多条消息写入单个文件或流由您来跟踪一条消息的结尾和下一条消息开始。协议缓冲区连线格式不是自定界的,因此协议缓冲区解析器无法确定消息在其拥有解决这个问题最简单的方法是写在您编写消息本身之前,先编写每条消息。当您阅读消息返回,您读取大小,然后将字节读取到单独的缓冲区,然后从该缓冲区进行解析。(如果你想避免将字节复制到单独的缓冲区,请检查CodedInputStream类(在C++和Java中),可以告诉它将读取限制为一定数量的字节。)

Protobuf不包括每个最外层记录的终止符,所以您需要自己完成。最简单的方法是在数据前面加上后面记录的长度。就我个人而言,我倾向于使用这样的方法:写一个字符串头(对于任意字段号),然后将长度写为"variant"——这意味着整个文档本身就是一个有效的protobuf,并且可以作为一个带有"repeated"元素的对象来使用,然而,只要一个固定长度(通常是32位的小端序)标记也可以。对于任何这样的存储,都可以根据需要进行附加。

如果您正在寻找C++解决方案,Kenton Varda在2015年8月左右向protobuf提交了一个补丁,增加了对writeDelimitedTo()和readDelimitedFrom()调用的支持,这些调用将以与Java版本的调用兼容的方式将一系列proto消息序列化到文件或从文件反序列化。不幸的是,该补丁尚未获得批准,因此如果你想要该功能,你需要自己将其合并。

另一种选择是谷歌通过其他项目提供开源的protobuf文件读/写代码。例如,or工具库包含将原型流序列化/反序列化为文件的类RecordReader和RecordWriter。

如果您想要这些类的几乎没有外部依赖关系的独立版本,我有一个或工具的分支,它只包含这些类。请参阅:https://github.com/moof2k/recordio

使用这些课程进行阅读和写作很简单:

File* file = File::Open("proto.log", "w");
RecordWriter writer(file);
writer.WriteProtocolMessage(msg1);
writer.WriteProtocolMessage(msg2);
...
writer.Close();

一种更简单的方法是对每条消息进行base64编码,并将其存储为每行的记录。

最新更新