option optimize_for=LITE_RUNTIME;
package MyPackage;
message ListHeader {
message Entry
{
optional string name = 1;
optional uint32 byte_offset_from_header = 2;
optional uint32 size_bytes = 3;
}
repeated Entry entry = 1;
}
You also need to keep track of how big your header is. Otherwise when
reading the header, it will happily just keep on going, accumulating
"unknown" tags/etc.
When you write the file, keep track of the actual offsets you write
the protos at. When reading, compare them to what you had when written
out... that should reveal the issue.
void WriteEntriesToFile(const string& path, .....other params here......)
{
ofstream* stream = new ofstream(path.c_str(), ios::out | ios::binary);
//.... check for stream validity here......
OFStreamWriter* writer = new OFStreamWriter(stream); // my own class which is a copy of OStreamOutputStream
::google::protobuf::io::CodedOutputStream* codedOut = new ::google::protobuf::io::CodedOutputStream(writer);
// Create new header
HeaderPB* headerPB = new HeaderPB();
unsigned int byteOffset = 0;
HeaderPB::EntryPB* entryPB = NULL;
// .... begin looping over instances of "MyMessage" to write to the file
{
entryPB = headerPB->add_resource_entry();
entryPB->set_resource_size_bytes(myMessagePB->ByteSize());
entryPB->set_resource_byte_offset_from_header(byteOffset);
byteOffset += myMessagePB->ByteSize();
}
// Write out size of header and header
codedOut->WriteLittleEndian32(headerPB->ByteSize());
headerPB->SerializeToCodedStream(codedOut);
// PRINT("BYTE OFFSET TO END OF HEADER %d", codedOut->ByteCount());
// Write out all the messages
// Again, loop over the messages passed in
{
// PRINT("CURRENT OFFSET FROM BEGGING OF FILE %d", codedOut->ByteCount());
myMessagePB->SerializeToCodedStream(codedOut);
}
delete headerPB;
delete codedOut;
delete writer;
delete stream;
}
</code>void GetMessagesFromFile(const string& path)
{
ifstream* stream = new ifstream(path.c_str(), ios::in | ios::binary);
unsigned int endOfHeaderOffset = 0;
// read_header_from_file just reads the HeaderPB and computes endOfHeaderOffset,
// via CodedInputStream CurrentPosition once parsing of header size and header is done.
// yes, read_header_from_file uses limits on the coded stream to not keep parsing
HeaderPB* header = read_header_from_file(path, stream, endOfHeaderOffset);
// Loop over the entries in the header
if ( 0 < header->entry_size() )
{
// Loop over all entries
MyMessagePb* myMessagePB = NULL;
IFStreamReader* reader = NULL;
::google::protobuf::io::CodedInputStream* coded = NULL;
// Loop from an index of 0 to header->entry_size()
{
const HeaderPB::EntryPB& entryProtoBuff = header->entry(entryIndex);
::google::protobuf::uint32 entrySize = entryProtoBuff.entry_size_bytes();
::google::protobuf::uint32 entryOffset = entryProtoBuff.entry_byte_offset_from_header();
// Put stream at byte offset and created IFStreamReader and CodedInputStream
// PRINT("BYTE OFFSET ON READING FROM BEGGING OF FILE %d", endOfHeaderOffset + entryOffset);
stream->seekg(endOfHeaderOffset + entryOffset, stream->beg);
reader = new IFStreamReader(stream);
coded = new ::google::protobuf::io::CodedInputStream(reader);
::google::protobuf::io::CodedInputStream::Limit oldLimit = coded->PushLimit(entrySize);
myMessagePB = new MyMessagePB();
if ( myMessagePB->ParseFromCodedStream(coded) )
{
// Code reaches this point, but all data in myMessagePB is null/not available via "has_xxxxx" function
// .... Do other stuff here......
}
coded->PopLimit(oldLimit);
delete coded;
delete reader;
}
}
delete header;
delete stream;
}