当使用谷歌协议缓冲区传输字符串字符时,得到了凌乱的代码

时间:2013-01-07 04:17:23

标签: java protocol-buffers

在调试视图中:

这是编码成凌乱字符串的代码......

((S2CEnterCollection)objS2c).toByteString().toStringUtf8();

输出:

    ���"default(
    ���"default(
    ���"default(
    ���"default(
    ���"default(
    ����"default(
    ����"default(
    �����"default(

以下是具有正确字符串的代码:

((S2CEnterCollection)objS2c).toString()

原始字符串是:

    cardList {
      cardId: 100001
      liked: 100
      number: 10
      finder: "default"
      rank: 1
    }
    cardList {
      cardId: 100002
      liked: 123
      number: 10
      finder: "default"
      rank: 1
    }
    cardList {
      cardId: 100003
      liked: 543
      number: 10
      finder: "default"
      rank: 1
    }
    cardList {
      cardId: 100004
      liked: 766
      number: 10
      finder: "default"
      rank: 1
    }
    cardList {
      cardId: 100005
      liked: 78
      number: 10
      finder: "default"
      rank: 1
    }
    cardList {
      cardId: 100006
      liked: 89
      number: 123
      finder: "default"
      rank: 1
    }
    cardList {
      cardId: 100007
      liked: 199
      number: 567
      finder: "default"
      rank: 1
    }
    cardList {
      cardId: 100008
      liked: 90909
      number: 232
      finder: "default"
      rank: 1
    }

那么,有没有人知道它是如何运作的?

3 个答案:

答案 0 :(得分:3)

protobuf数据是二进制的,不是编码文本。你不能通过像UTF-8这样的编码来运行它,并期望获得一个字符串(或者期望它仍然有效)。将protobuf数据转换为字符串的唯一方法是通过base-N编码运行一些N,通常为64(因为它在大多数平台上都得到很好的支持)。

答案 1 :(得分:2)

这个凌乱的字符串可能绝对正确。问题是:你假设它是一个人类可读的字符串,而事实并非如此。 toByteString(),我引用:

Serializes the message to a ByteString and returns it. This is just a trivial wrapper around writeTo(CodedOutputStream).

https://developers.google.com/protocol-buffers/docs/reference/java/index - 寻找MessageLite。

这可能是您可能用于通过网络传输的格式,或者您可能存储在具有数百万条记录的文件中的格式。它并不意味着人类可读 - 它意味着相对较小的机器可读表示。因此它使用标签标识符(小数字)而不是字段名称,可变长度编码和各种其他技巧来实现最小化大小而牺牲可读性。

https://developers.google.com/protocol-buffers/docs/encoding

答案 2 :(得分:1)

我更喜欢使用Google自己的com.google.protobuf.TextFormat类,该类使用“print”方法构造Protobuf对象内容的可读表示形式。在下面的示例中,PayloadContent可以是任何消息:

PayloadContent pc = PayloadContent.newBuilder().setContent........build();
String text = TextFormat.shortDebugString(pc);

如果你想要看到“Byte”格式,那么肯定会将ByteString表示转换为Base64 - 但这对于人类阅读并没有太大用处:)