String.getBytes 是否被安全使用?

Is String.getBytes being safely used?

目前,我需要处理 Java 中字符串的字节,这引发了很多关于 JVM 的编码和实现细节的问题。我想知道我做的是有意义的,还是多余的。

首先,我了解到在运行时,字符串中的 Java 字符将 始终 表示 Unicode 中的符号。

其次,UTF-8编码总是能够成功编码Unicode中的任何符号。反过来,下面的代码片段将 always return a byte[] 而不做任何替换。 getBytes 文档是 here.

byte[] stringBytes = myString.getBytes(StandardCharsets.UTF_8);

然后,如果 stringBytes 以下列方式在不同的 JVM 实例中使用,它将总是 产生一个等同于 myString 的字符串。

new String(stringBytes, StandardCharsets.UTF_8);

您认为我对getBytes的理解正确吗?如果是这样的话,你会如何证明它的合理性?我是否遗漏了一个可能导致我得不到 myString 的等效版本的病态案例?

提前致谢。


编辑:

您是否同意通过执行以下任何非异常流程都会导致处理案例,从而使我们能够成功地重建字符串?


编辑:

根据答案,这里有一个解决方案,它允许您在没有抛出异常的情况下安全地重建字符串。您仍然需要以某种方式处理异常。

首先,使用编码器获取字节:

final CharsetEncoder encoder =
    StandardCharsets.UTF_8.
        .newEncoder()
        .onUnmappableCharacter(CodingErrorAction.REPORT)
        .onMalformedInput(CodingErrorAction.REPORT);


// It throws a CharacterCodingException in case there is a replacement or malformed string
// The given array is actually bigger than required because it is the internal array used by the ByteBuffer. Read its doc.
byte[] stringBytes = encoder.encode(CharBuffer.wrap(string)).array();

其次,使用编码器给出的字节构造字符串(非异常路径):

new String(stringBytes, StandardCharsets.UTF_8);

it will always yield a string equivalent to myString.

好吧,不是 总是。这个世界上发生的事情不多总是

我能想到的一个极端情况是,当您调用 getBytes 时,myString 可能是一个“无效”字符串。例如,它可能有一个单独的代理对:

String myString = "\uD83D";

这种情况发生的频率在很大程度上取决于您使用 myString 做什么,所以我会让您自己考虑一下。

如果 myString 有一个单独的代理对,getBytes 将为其编码一个问号字符:

// prints "?"
System.out.println(
    new String(myString.getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8)
);

我不会说 ? 与格式错误的字符串“等价”。

另请参阅: