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 <samvel.khalat...@gmail.com> 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 protobuf@googlegroups.com.
> To unsubscribe from this group, send email to
> protobuf+unsubscr...@googlegroups.com.
> 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 protobuf@googlegroups.com.
To unsubscribe from this group, send email to 
protobuf+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/protobuf?hl=en.

Reply via email to