【问题标题】:Google Protobuf ByteString vs. Byte[]Google Protobuf ByteString 与 Byte[]
【发布时间】:2015-05-15 02:51:44
【问题描述】:

我正在使用 Java 中的 google protobuf。 我看到可以将 protobuf 消息序列化为 String、byte[]、ByteString 等: (来源:https://developers.google.com/protocol-buffers/docs/reference/java/com/google/protobuf/MessageLite

我不知道 ByteString 是什么。我从 protobuf API 文档中得到了以下定义(来源:https://developers.google.com/protocol-buffers/docs/reference/java/com/google/protobuf/ByteString): “不可变的字节序列。通过共享对不可变底层字节的引用来支持子字符串,就像字符串一样。”

我不清楚 ByteString 与 String 或 byte[] 有何不同。 有人可以解释一下吗? 谢谢。

【问题讨论】:

    标签: java string bytearray protocol-buffers


    【解决方案1】:

    您可以将ByteString 视为一个不可变的字节数组。差不多就是这样。这是一个byte[],您可以在 protobuf 中使用它。 Protobuf 不允许您使用 Java 数组,因为它们是可变的。

    ByteString 存在是因为String 不适合表示任意字节序列。 String 专门用于字符数据。

    protobuf MessageLite 接口提供 toByteArray() 和 toByteString() 方法。如果 ByteString 是一个不可变的 byte[],那么 ByteString 和 byte[] 所表示的消息的字节表示是否相同?

    有点。如果您调用toByteArray(),您将获得与调用toByteString().toByteArray() 相同的值。比较两种方法的实现,在AbstractMessageLite

    public ByteString toByteString() {
      try {
        final ByteString.CodedBuilder out =
          ByteString.newCodedBuilder(getSerializedSize());
        writeTo(out.getCodedOutput());
        return out.build();
      } catch (IOException e) {
        throw new RuntimeException(
          "Serializing to a ByteString threw an IOException (should " +
          "never happen).", e);
      }
    }
    
    public byte[] toByteArray() {
      try {
        final byte[] result = new byte[getSerializedSize()];
        final CodedOutputStream output = CodedOutputStream.newInstance(result);
        writeTo(output);
        output.checkNoSpaceLeft();
        return result;
      } catch (IOException e) {
        throw new RuntimeException(
          "Serializing to a byte array threw an IOException " +
          "(should never happen).", e);
      }
    }
    

    【讨论】:

    • protobuf MessageLite 接口提供 toByteArray() 和 toByteString() 方法。如果 ByteString 是一个不可变的 byte[],那么 ByteString 和 byte[] 所表示的消息的字节表示是否相同?
    • writeTo 定义在哪里?
    • @LeiYang 是declared on the MessageLite interface,实现是每个生成的 protobuf 类的一部分。
    【解决方案2】:

    ByteString 使您能够对基础数据执行更多操作,而无需将数据复制到新结构中。例如,如果您想将byte[] 中的bytes 的子集提供给另一个方法,则需要为其提供开始索引和结束索引。您还可以连接ByteStrings,而无需创建新的数据结构并手动复制数据。

    但是,使用ByteString,您可以为该方法提供该数据的一个子集,而无需该方法对底层存储有任何了解。就像普通字符串的子字符串一样。

    字符串用于表示文本,不是存储二进制数据的好方法(因为并非所有二进制数据都有文本等价物,除非您以这样的方式对其进行编码:例如 hex 或 Base64 )。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多