c # — проблема десериализации (protocolBuffer) сериализованных данных с использованием protobuf-net

Я сериализовал данные с использованием protobuf-Net, и я могу сделать то же самое в 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 ++ с использованием протокола-буфера, я не могу получить правильные данные

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?

Я уверен, что делаю ошибку, но не в состоянии понять, что не так …. Прочитал и перечитал много постов по этому вопросу, но не вижу, что по-прежнему не так

Использование протокола Buffer2.5, protobuf-netR622, Visual Studio 2010

1

Решение

Я думаю, что вы просто не соответствуете заголовкам; префикс длины а также заголовок поля (поля 1) два «varint» с; первый «varint» всегда будет десятичным 10 (10 означает: поле 1, с префиксом длины). второй «varint» сообщает вам длину следующих данных. Так что — если вы хотите расшифровать его вручную ты бы позвонил ReadVarint32 второй время. Я не знаком с ReadRaw, но если вторым параметром является число байтов для чтения, то это идет туда, то есть

coded_in->ReadVarint32(&n); // field header
// assert: n === 10
coded_in->ReadVarint32(&n); // length
coded_in->ReadRaw(&tmpStr,n);

В качестве альтернативы, просто используйте объект-оболочку, т.е.

message animals {
repeated animal items = 1;
}

и десериализовать это как пример animals — это использует точно такой же макет. Единственная разница здесь в том, что он будет загружать все элементы за один раз — так что это может быть проблематично, если вы читаете очень длинные потоки.

Другой альтернативой будет: не добавлять заголовок поля:

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

Тогда вы читаете только один «вариант»:

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

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]