我使用Google Protobuf 2.6.1创建了一个非常简单的java类,具有以下结构:
required int64 tid = 1;
required int64 tid = 1;
required string clOrdID = 2;
required string execID = 3;
required string ticketType = 4;
optional string lastMkt = 5;
required double lastQty = 6;
required double cumQty = 7;
required double lastPx = 8;
required double avgPx = 9;
optional string lastCapacity = 10;
required int64 transactionTime = 11;
required int64 reportTime = 12;
构建类并使用测试数据填充这些字段后,我使用.toByteArray()方法将其转换为字节数组:
double d = 99.0;
FillProto fillProto = FillProto.newBuilder()
.setTid(n)
.setClOrdID("ClOrdID")
.setExecID("ExecID")
.setTicketType("ticketType")
.setLastMkt("LastMkt")
.setLastQty(d)
.setCumQty(d)
.setLastPx(d)
.setAvgPx(d)
.setLastCapacity("LastCapacity")
.setTransactionTime(now.getTime())
.setReportTime(now.getTime())
.build();
Log.info(class_,method_,"Sending through:\n" + new String(fillProto.toByteArray()));
我通过Solace队列发送ByteArray,在另一方使用后,我尝试使用FillProto.parseFrom(byte [])构建另一个对象,但得到一个错误:"解析协议消息时,输入意外地在一个字段中间结束。"。 ByteArray看起来很好,直到标记为double的字段为止,这些字段都输出为null(00字节)。有谁知道这里发生了什么?
下面的字节数组:
08 05 12 07 63 6c 4f 72 64 49 44 1a 06 65 78 65 ....clOrdID..exe
63 49 44 22 0a 74 69 63 6b 65 74 54 79 70 65 2a cID".ticketType*
07 6c 61 73 74 4d 6b 74 31 00 00 00 00 00 c0 58 .lastMkt1......X
40 39 00 00 00 00 00 c0 58 40 41 00 00 00 00 00 @9......X@A.....
c0 58 40 49 00 00 00 00 00 c0 58 40 52 0c 4c 61 .X@I......X@R.La
73 74 43 61 70 61 63 69 74 79 58 b0 8b a8 ce e6 stCapacityX.....
29 60 b0 8b a8 ce e6 29 )`.....)
答案 0 :(得分:3)
这很正常。使用标准的8字节IEEE-754表示来表示双打。双值零表示为全零,大多数其他值也包含零。
听起来您的消息传递基础架构设计用于在NUL终止的文本字符串上运行。此类基础结构不适用于原始Protobuf内容,因为它将在第一个NUL字节处截断消息。通常,您不能在为文本设计的上下文中使用原始Protobuf数据,因为可能会发生各种损坏。请特别注意,永远不要将protobuf字节传递给new String()
,因为String
存储Unicode文本,而不是字节。
如果您需要在需要文本的地方传输Protobufs,则需要对数据进行base64编码以防止此类损坏 - base64允许将原始字节放置在文本上下文中,但会增加数据的整体大小33%。