Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deserializing a type at the current stream position with protobuf-net

I'm serializing several objects into a single stream, but when i try to read them back, i can't seem to get anything but the last object:

ProtoBuf.Serializer.Serialize(stream, postA1);
ProtoBuf.Serializer.Serialize(stream, postB1);
stream.Position = 0;
var postA2 = ProtoBuf.Serializer.Deserialize<Post>(stream);
var postB2 = ProtoBuf.Serializer.Deserialize<Post>(stream);

The first deserialize moves the stream to the end and postA2 contains the value of postB1, while postB2 is just an uninitialized instance. Is this expected behavior, and if so, how do you deserialize an object from a random position in a stream?

like image 904
Arne Claassen Avatar asked Mar 14 '10 08:03

Arne Claassen


1 Answers

By default, protobuf (the Google spec, not proobuf-net specifically) is designed to allow you to treat consecutive messages as part of a single object - i.e. you can add fields to a message simply by concatenating, which is essentially what you are doing here. Each top-level object does not (by default) have any kind of separation from the next object.

To get it to treat them as different objects, look at the *WithLengthPrefix methods (or you can use the IEnumerable<T> versions - perhaps DeserializeItems; note also that it will apply length prefixes automatically if you give it something like a list to serialize); for example:

Essentially:

Serializer.SerializeWithLengthPrefix(stream, postA1, PrefixStyle.Base128, 1);
Serializer.SerializeWithLengthPrefix(stream, postB1, PrefixStyle.Base128, 1);
stream.Position = 0;
var postA2 = Serializer.DeserializeWithLengthPrefix<Post>(stream,
    PrefixStyle.Base128, 1);
var postB2 = Serializer.DeserializeWithLengthPrefix<Post>(stream,
    PrefixStyle.Base128, 1);
like image 106
Marc Gravell Avatar answered Sep 21 '22 17:09

Marc Gravell