如何编码/解码协议缓冲区二进制数据(整数)到字符串和字符串到二进制?

时间:2015-03-26 06:02:29

标签: java encoding base64 protocol-buffers decoding

我正在使用协议缓冲区 smack 制作程序。

smack(xmpp)只能传输字符串类型数据。和协议缓冲区可以产生字节数组数据。 所以,我这样做

  1. 使用协议缓冲区生成byte []数据。
  2. 使用base64将byte []数据编码为字符串
  3. 使用smack转移
  4. 将接收到的字符串(使用base64编码)解码为字符串
  5. 将解码后的字符串更改为byte []
  6. 使用协议缓冲区解析来自byte []的数据。
  7. 然后每个值都是完美的,没有Integer类型值。 Integer的值已更改。 值在xxxx.proto

    例如转换string abc = "hello" int age = 13300  到string abc = "hello" int age = 217014255

    只有int被更改

    问题是什么?

1 个答案:

答案 0 :(得分:0)

  
      
  1. 将接收到的字符串(使用base64编码)解码为字符串
  2.   
  3. 将解码后的字符串更改为byte []
  4.   

由于您还没有提供代码,因此很难确定,但我怀疑这些步骤看起来像这样:

String encoded = readMessage();
String decoded = new String(base64Decode(encoded), "ASCII");
byte[] bytes = decoded.getBytes("UTF-8");

这是错误的,因为你在这里实际做的是将解码的字节解释为ASCII字符串,然后使用UTF-8编码将它们转换回字节。我相信这会导致你描述的腐败:如果你看一下字节模式,你会发现原始消息只有一个字节,其顶部位设置(使其无效的ASCII),并且在损坏的情况下消息,该字节已被Unicode替换字符的UTF-8编码替换(用于标记错误)。您的字符串数据没有损坏,因为它只包含ASCII,并且Protobuf元数据没有被破坏,因为您的字段编号都不大于15,因此标记都是1字节而没有设置高位(这使得它们成为有效的ASCII)。

在任何情况下,String类都不能包含原始字节。它只能包含Unicode文本。因此,将base64Decode()的输出表示为String是错误的。它必须只是byte[]。也就是说,它应该看起来像:

String encoded = readMessage();
byte[] decoded = base64Decode(encoded);