我正在尝试使用 C++ 和 Java 从文件中读取/写入多个协议缓冲区消息。Google 建议在消息之前编写长度前缀,但默认情况下没有办法做到这一点(我可以看到)。
但是,2.1.0 版中的 Java API 收到了一组“分隔的”I/O 函数,它们显然可以完成这项工作:
parseDelimitedFrom
mergeDelimitedFrom
writeDelimitedTo
有 C++ 等价物吗?如果没有,Java API 附加的大小前缀的有线格式是什么,以便我可以在 C++ 中解析这些消息?
更新:
这些现在存在于google/protobuf/util/delimited_message_util.h
v3.3.0 中。
我在这里参加聚会有点晚了,但是下面的实现包括其他答案中缺少的一些优化,并且在输入 64MB 后不会失败(尽管它仍然对每条消息强制执行64MB 限制,只是不在整个流上)。
(我是 C++ 和 Java protobuf 库的作者,但我不再为 Google 工作。抱歉,这段代码从未进入官方库。这就是它的样子。)
bool writeDelimitedTo( const google::protobuf::MessageLite& message, google::protobuf::io::ZeroCopyOutputStream* rawOutput) { // We create a new coded stream for each message. Don't worry, this is fast. google::protobuf::io::CodedOutputStream output(rawOutput); // Write the size. const int size = message.ByteSize(); output.WriteVarint32(size); uint8_t* buffer = output.GetDirectBufferForNBytesAndAdvance(size); if (buffer != NULL) { // Optimization: The message fits in one buffer, so use the faster // direct-to-array serialization path. message.SerializeWithCachedSizesToArray(buffer); } else { // Slightly-slower path when the message is multiple buffers. message.SerializeWithCachedSizes(&output); if (output.HadError()) return false; } return true; } bool readDelimitedFrom( google::protobuf::io::ZeroCopyInputStream* rawInput, google::protobuf::MessageLite* message) { // We create a new coded stream for each message. Don't worry, this is fast, // and it makes sure the 64MB total size limit is imposed per-message rather // than on the whole stream. (See the CodedInputStream interface for more // info on this limit.) google::protobuf::io::CodedInputStream input(rawInput); // Read the size. uint32_t size; if (!input.ReadVarint32(&size)) return false; // Tell the stream not to read beyond that size. google::protobuf::io::CodedInputStream::Limit limit = input.PushLimit(size); // Parse the message. if (!message->MergeFromCodedStream(&input)) return false; if (!input.ConsumedEntireMessage()) return false; // Release the limit. input.PopLimit(limit); return true; }