我使用协议缓冲区使用c ++程序创建了一个二进制文件。我在C#程序中读取二进制文件时遇到了问题,所以我决定编写一个小的c ++程序来测试读数。
我的原型文件如下
message TradeMessage {
required double timestamp = 1;
required string ric_code = 2;
required double price = 3;
required int64 size = 4;
required int64 AccumulatedVolume = 5;
}
写入协议缓冲区时,我先写对象类型,然后是对象长度和对象本身。
coded_output->WriteLittleEndian32((int) ObjectType_Trade);
coded_output->WriteLittleEndian32(trade.ByteSize());
trade.SerializeToCodedStream(coded_output);
现在,当我尝试在我的c ++程序中读取相同的文件时,我看到了奇怪的行为。
我的阅读代码如下:
coded_input->ReadLittleEndian32(&objtype);
coded_input->ReadLittleEndian32(&objlen);
tMsg.ParseFromCodedStream(coded_input);
cout << "Expected Size = " << objlen << endl;
cout<<" Trade message received for: "<< tMsg.ric_code() << endl;
cout << "TradeMessage Size = " << tMsg.ByteSize() << endl;
在这种情况下,我得到以下输出
Expected Size = 33
Trade message received for: .CSAP0104
TradeMessage Size = 42
当我写入文件时,我将trade.ByteSize()写为33个字节,但是当我读取同一个对象时,对象ByteSize()是42个字节,这会影响其余的数据。我不确定这有什么问题。请指教。
此致 阿洛克
答案 0 :(得分:1)
根据上述情况,这是猜测:当您使用ParseFromCodedStream
时,实际上并没有将其限制为您之前找到的objlen
;因此,如果流包含的数据多于此数据(即不是文件的末尾),则引擎将尝试继续读取EOF。你必须根据你的期望限制长度。我不是C ++专家,所以我不能提供直接指导,但如果这是C#(使用protobuf-net):
objType = ProtoReader.DirectReadLittleEndianInt32(file);
len = ProtoReader.DirectReadLittleEndianInt32(file);
// assume GetObjectType returns typeof(TradeMessage) for our objType
Type type = GetObjectType(objType);
msg = RuntimeTypeModel.Default.Deserialize(file, null, type, len, null);
答案 1 :(得分:1)
显然,我在创建二进制文件时犯了一个非常愚蠢的错误。当我向它写入protobuf数据时,我没有以二进制模式打开文件,导致它在中间添加奇怪的ascii字符。这在使用protobuf-net库读取数据时引起了问题。这个问题在这里解决了。不应该花这么长时间来解决这个问题。