0

I am making program using Protocol buffer and smack.

smack (xmpp) only can transfer string type data. and protocol buffer can produce byte array data. so, i do this

  1. make byte[] data using protocol buffer.
  2. encode byte[] data to string using base64
  3. transfer using smack
  4. decode received string(encoded using base64) to string
  5. change decoded string to byte[]
  6. parse data from byte[] using protocol buffer.

then every values are perfect without Integer type value. the value of Integer is changed. the values are in xxxx.proto

for instance converting string abc = "hello" int age = 13300 to string abc = "hello" int age = 217014255

only int is changed

what is the problem?

AdrieanKhisbe
  • 3,899
  • 8
  • 37
  • 45
dolseobi
  • 3
  • 1
  • 3

1 Answers1

0
  1. decode received string(encoded using base64) to string
  2. change decoded string to byte[]

Since you haven't provided code, it's hard to tell for sure, but I suspect these steps look something like this:

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

This is wrong, because what you are actually doing here is interpreting the decoded bytes as an ASCII string, and then converting them back to bytes with UTF-8 encoding. I believe this will cause exactly the corruption you describe: if you look at the byte pattern, you'll see that the original message has exactly one byte which has the top bit set (making it invalid ASCII), and in the corrupted message that byte has been replaced by the UTF-8 encoding of the Unicode replacement character (used to mark errors). Your string data is not corrupted because it contains only ASCII, and the Protobuf metadata was not corrupted because none of your field numbers are greater than 15 and therefore the tags are all 1 byte without the high bit set (which makes them valid ASCII).

In any case, the String class cannot contain raw bytes. It can only contain Unicode text. So it is wrong for the output of base64Decode() to ever be represented as a String. It must only be byte[]. That is, it should look like:

String encoded = readMessage();
byte[] decoded = base64Decode(encoded);
Kenton Varda
  • 41,353
  • 8
  • 121
  • 105
  • The problem is.... string(base64) -> string(ascii) -> byte[] now i changed it as you told string(base64) -> byte[] directly and it works~!! thank you~ – dolseobi Mar 27 '15 at 02:20