Я сериализовал данные с использованием 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) два «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);
Других решений пока нет …