1

protobuf-net を使用してデータをシリアル化し、C# で同じことを行うことができます。

C# ダミー 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();

これまでのところ、問題はありません。しかし、プロトコル バッファを使用して C++ で同じものを逆シリアル化しようとすると、正しいデータを取得できません。

cppコード...

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?

私は間違いを犯していると確信していますが、何が間違っているのか理解できません....これに関する多くの投稿を読んで再読しましたが、まだ何が間違っているのかわかりません

Protocol Buffer2.5、protobuf-netR622、Visual Studio 2010 を使用

4

1 に答える 1

0

ヘッダーが一致していないだけだと思います。length-prefixfield-header (フィールド 1 の) は2 つの「varint」です。最初の「varint」は常に 10 進数の 10 になります (10 は、フィールド 1、長さの接頭辞が付いていることを意味します)。2 番目の varint」は、次のデータの長さを示します。したがって、手動でReadVarint32デコードする場合は、もう一度呼び出します。私はよく知りませんReadRawが、2番目のパラメーターが読み取るバイト数の場合、そこに移動します。つまり

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

次に、1つの「varint」のみを読み取ります。

coded_in->ReadVarint32(&n); // length
coded_in->ReadRaw(&tmpStr,n);
于 2013-05-10T12:34:23.560 に答える