I'm trying to read / write multiple Protocol Buffers messages from files, in both C++ and Java. Google suggests writing length prefixes before the messages, but there's no way to do that by default (that I could see).
However, the Java API in version 2.1.0 received a set of "Delimited" I/O functions which apparently do that job:
parseDelimitedFrom
mergeDelimitedFrom
writeDelimitedTo
Are there C++ equivalents? And if not, what's the wire format for the size prefixes the Java API attaches, so I can parse those messages in C++?
Update:
These now exist in google/protobuf/util/delimited_message_util.h
as of v3.3.0.
Was also looking for a solution for this. Here's the core of our solution, assuming some java code wrote many MyRecord messages with
writeDelimitedTo
into a file. Open the file and loop, doing:Hope it helps.
IsteamInputStream is very fragile to eofs and other errors that easily occurs when used together with std::istream. After this the protobuf streams are permamently damaged and any already used buffer data is destroyed. There are proper support for reading from traditional streams in protobuf.
Implement
google::protobuf::io::CopyingInputStream
and use that together with CopyingInputStreamAdapter. Do the same for the output variants.In practice a parsing call ends up in
google::protobuf::io::CopyingInputStream::Read(void* buffer, int size)
where a buffer is given. The only thing left to do is read into it somehow.Here's an example for use with Asio synchronized streams (SyncReadStream/SyncWriteStream):
Usage:
Here you go:
Since I'm not allowed to write this as a comment to Kenton Varda's answer above; I believe there is a bug in the code he posted (as well as in other answers which have been provided). The following code:
sets an incorrect limit because it does not take into account the size of the varint32 which has already been read from input. This can result in data loss/corruption as additional bytes are read from the stream which may be part of the next message. The usual way of handling this correctly is to delete the CodedInputStream used to read the size and create a new one for reading the payload: