本文介绍了使用 protobuf-net 发出反序列化 (protocolBuffer) 序列化数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用 protobuf-net 序列化数据,并且能够在 C# 中设计相同的数据.

I serialized data using protobuf-net, and am able to deser the same in C#.

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();

到目前为止一切顺利……这里没有问题.但是当我尝试使用协议缓冲区在 C++ 中反序列化相同的内容时,我无法获得正确的数据

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

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

使用协议 Buffer2.5、protobuf-netR622、Visual Studio 2010

Using Protocol Buffer2.5, protobuf-netR622, Visual Studio 2010

推荐答案

我认为您只是标题不匹配;长度前缀字段头(字段 1)是两个varint";第一个varint"将始终是十进制 10(10 表示:字段 1,长度为前缀).second "varint" 告诉你下一个数据的长度.所以 - 如果你想手动解码它,你会第二次调用ReadVarint32.我不熟悉 ReadRaw,但如果第二个参数是要读取的字节数,那么 它就在那里,即

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;
}

并将其反序列化作为animals的一个实例——这使用完全相同的布局.这里唯一的区别是它会一次性加载所有项目 - 因此如果您正在阅读很长的流,这可能会出现问题.

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.

另一种选择是:不要添加字段标题:

Serializer.SerializeWithLengthPrefix(file, animal, PrefixStyle.Base128, 0);

那么你只会读取一个varint":

Then you would only read one "varint":

coded_in->ReadVarint32(&n); // length
coded_in->ReadRaw(&tmpStr,n);

这篇关于使用 protobuf-net 发出反序列化 (protocolBuffer) 序列化数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-02 11:13