Issue deserializing (protocolBuffer) serialized data using protobuf-net

空扰寡人 提交于 2019-12-08 07:44:10

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!