问题
I serialized data using protobuf-net, and am able to deser the same in C#.
putting a C# dummy w#
var file = File.Create("animal.bin");
//Creating Msg - Fill the Data
animal.id = "1";
animal.Name = "Rat";
animal.host = "Cheetha";
ProtoBuf.Serializer.SerializeWithLengthPrefix(file, animal, PrefixStyle.Base128, 1);
animal.id = "2";
animal.Name = "Cat";
animal.host = "Cheetha";
ProtoBuf.Serializer.SerializeWithLengthPrefix(file, animal, PrefixStyle.Base128, 1);
....
animal.id = "4";
animal.name = "Cheetha";
animal.host = "Cheetha";
ProtoBuf.Serializer.SerializeWithLengthPrefix(file, animal, PrefixStyle.Base128, 1);
//Done Creating Msg
file.Close();
So far so good... No Issues here. But when I try to deserialize the same in C++ using protocol-buffer, I am unable to get the correct data
cpp code...
GOOGLE_PROTOBUF_VERIFY_VERSION;
string fpath = "animal.bin";
fstream input(fpath, ios::in | ios::binary);
if (!input)
{
cerr << "failed to open " << fpath << endl;
return false;
}
ZeroCopyInputStream *raw_in = new IstreamInputStream(&input);
CodedInputStream *coded_in = new CodedInputStream(raw_in);
google::protobuf::uint32 n;
std::string tmpStr;
animal::animalInfo animalList;
coded_in->ReadVarint32(&n);
cout << "# " << n << endl; //output: #10
coded_in->ReadRaw(&tmpStr,n); //tmpStr shows data like >>1..Rat..Ch
animalList.ParseFromArray(&tmpStr,1);//Not sure if this is correct usage?
I am sure I am making a mistake but not able to understand whats wrong.... Have read and reread lots of post on this but dont see whats still wrong
Using Protocol Buffer2.5, protobuf-netR622, Visual Studio 2010
回答1:
I think you're just mismatching the headers; a length-prefix and a field-header (of field 1) is two "varint"s; the first "varint" will always be decimal 10 (10 means: field 1, length-prefixed). The second "varint" tells you the length of the next data. So - if you want to decode it manually you would call ReadVarint32
a second time. I'm not familiar with ReadRaw
, but if the second parameter is the number of bytes to read, then it goes there, i.e.
coded_in->ReadVarint32(&n); // field header
// assert: n === 10
coded_in->ReadVarint32(&n); // length
coded_in->ReadRaw(&tmpStr,n);
Alternatively, just use a wrapper object - i.e.
message animals {
repeated animal items = 1;
}
and deserialize it as an instance of animals
- this uses the exact same layout. The only difference here is that it will load all the items in one go - so it might be problematic if you are reading very long streams.
Another alternative would be: don't add a field-header:
Serializer.SerializeWithLengthPrefix(file, animal, PrefixStyle.Base128, 0);
Then you would only read one "varint":
coded_in->ReadVarint32(&n); // length
coded_in->ReadRaw(&tmpStr,n);
来源:https://stackoverflow.com/questions/16473083/issue-deserializing-protocolbuffer-serialized-data-using-protobuf-net