Varint does an encoding whose length changes with the size of the number - hence the name. So it can use between 1 and 10 bytes. So when the value _events_written changes, re-writing the same number at the beginning of the file will use a different number of bytes.
If you want to write a number that changes like this to a particular position, you need to use a fixed size number encoding (e.g. fixed32 or fixed64) to do so. On Fri, Mar 4, 2011 at 16:22, ksamdev <[email protected]> wrote: > I have an application where number of messages is a priory unknown. I can > open output file and write 0 in the beginning: > Writer::Writer(const string &filename): > _output(filename.c_str(), ios::out | ios::trunc | ios::binary), > _events_written(0) > { > _raw_out.reset(new > ::google::protobuf::io::OstreamOutputStream(&_output)); > _coded_out.reset(new > ::google::protobuf::io::CodedOutputStream(_raw_out.get())); > _coded_out->WriteVarint32(_events_written); At this time, _events_written is zero, which, encoded, uses a different length in the file ... > } > and then in the destructor reset the position in the ofstream to the > beginning to write the number of the events: > Writer::~Writer() > { > _coded_out.reset(); > _raw_out.reset(); > _output.seekp(0); > // Small trick to save number of the events > // > _raw_out.reset(new > ::google::protobuf::io::OstreamOutputStream(&_output)); > _coded_out.reset(new > ::google::protobuf::io::CodedOutputStream(_raw_out.get())); > _coded_out->WriteVarint32(_events_written); ... than here: _events_written is a larger number, encoded with more bytes, so it will overwrite parts of the following data .. > _coded_out.reset(); > _raw_out.reset(); > _output.close(); > } > Then read the beginning of the file with number of the events: > Reader::Reader(const string &filename): > _input(filename.c_str(), ios::in | ios::binary), > _is_good(true), > _events_written(0) > { > _raw_in.reset(new ::google::protobuf::io::IstreamInputStream(&_input)); > _coded_in.reset(new > ::google::protobuf::io::CodedInputStream(_raw_in.get())); > _coded_in->ReadVarint32(&_events_written); > } > Everything seems fine. Then events can be read one by one like: > bool Reader::read(Event &event) > { > event.Clear(); > uint32_t message_size; > if (!_coded_in->ReadVarint32(&message_size)) ... so here you have a number, whose beginning is partially overwritten by the end of the re-written events list -> the reading fails. > { > _is_good = false; > return false; > } > if (0 < message_size) > { > string message; > if (!_coded_in->ReadString(&message, message_size) || > !event.ParseFromString(message)) > return false; > } > return true; > } > Unfortunately, ReadVarint32 fails for some reason in the Reader::read(...) > method. > The code works fine in case I do not use seekp in the Writer::~Writer(). > What is the proper way to seek to the beginning of the file and store number > of entries? > > -- > You received this message because you are subscribed to the Google Groups > "Protocol Buffers" group. > To post to this group, send email to [email protected]. > To unsubscribe from this group, send email to > [email protected]. > For more options, visit this group at > http://groups.google.com/group/protobuf?hl=en. > -- You received this message because you are subscribed to the Google Groups "Protocol Buffers" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/protobuf?hl=en.
