Google协议缓冲区 - 将邮件存储到文件中

DD.*_*DD. 37 protocol-buffers

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

如何将多条消息存储到一个文件中?不知道如何分隔消息.我需要能够动态地将新消息附加到文件中.

Jos*_*sen 31

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

  • @AndrewHundt C++等价物由Protobuf C++库的作者提供[stackoverflow answer](http://stackoverflow.com/a/22927149/757777) (7认同)

DD.*_*DD. 13

来自文档:

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

流式传输多条消息

如果要将多条消息写入单个文件或流,则需要跟踪一条消息的结束位置和下一条消息的开始位置.协议缓冲区有线格式不是自定界限的,因此协议缓冲区解析器无法确定消息自身的结束位置.解决此问题的最简单方法是在编写消息本身之前写入每条消息的大小.当您重新读取消息时,读取​​大小,然后将字节读入单独的缓冲区,然后从该缓冲区解析.(如果你想避免将字节复制到一个单独的缓冲区,请查看CodedInputStream类(在C++和Java中),可以告诉它将读取限制为一定的字节数.)


Mar*_*ell 6

Protobuf不包括每个最外层记录的终结符,因此您需要自己执行此操作.最简单的方法是在数据前加上后面记录的长度.就个人而言,我倾向于使用编写字符串标题的方法(对于任意字段编号),然后将长度作为"varint" - 这意味着整个文档本身就是一个有效的protobuf,并且可以作为对象使用然而,使用"重复"元素,只需一个固定长度(通常是32位小端)标记也可以.对于任何此类存储,它可以根据您的需要进行附加.

  • 要将几个protobuf消息写入流/文件,请将输出流包装到CodedOutputStream`CodedOutputStream writer = CodedOutputStream.newInstance(outputStreamToWrite); writer.writeRawVarint32(bytes.length); writer.writeRawBytes(bytes);`读取整个文件:`CodedInputStream is = CodedInputStream.newInstance(inputStreamToWrap); while(!is.isAtEnd()){int size = is.readRawVarint32(); YourMessage.parseFrom(is.readRawBytes(大小);}` (5认同)

moo*_*f2k 5

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

另一个选择是Google通过其他项目开源protobuf文件读写代码。该或工具库,例如,包含的类RecordReaderRecordWriter的进行序列化/反序列化原流到文件。

如果您希望这些类的独立版本几乎没有外部依赖性,那么我有一个or-tools分支,其中仅包含这些类。参见:https : //github.com/moof2k/recordio

使用这些类进行读写很简单:

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