谷歌 Protobuf ByteString 和 Byte[] 的区别

45

我正在使用Java中的Google Protobuf。我发现可以将protobuf消息序列化为String、byte[]、ByteString等格式:

(Source: 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): “不可变的字节序列。通过共享对不可变底层字节的引用来支持子字符串,就像String一样。”

对我来说不清楚ByteString与String或byte[]有什么区别。能否有人解释一下? 谢谢。

2个回答

49

你可以将ByteString视为不可变的字节数组。就是这样。它是一个可以在protobuf中使用的byte[]。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[]表示的消息的字节表示是否相同? - Rahim Pirbhai
writeTo 定义在哪里? - Lei Yang
1
@LeiYang 它被声明在 MessageLite 接口上(https://developers.google.com/protocol-buffers/docs/reference/java/com/google/protobuf/MessageLite),并且实现是每个生成的 protobuf 类的一部分。 - Matt Ball

10
ByteString提供了更多的操作能力,而不需要将数据复制到一个新的结构中。例如,如果您想要在byte[]中提供一部分bytes给另一个方法,您需要为其提供一个起始索引和一个结束索引。您还可以连接ByteStrings,而不需要创建一个新的数据结构并手动复制数据。
然而,使用ByteString,您可以为该方法提供该数据的子集,而该方法无需知道底层存储的任何信息。就像普通字符串的子字符串一样。
字符串用于表示文本,不是存储二进制数据的好方法(除非您以一种具有文本等效项的方式对其进行编码:例如十六进制或Base64)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接