目前,我需要在Java中处理字符串的字节,这引发了许多关于编码和JVM实现细节的问题。我想知道我正在做的事情是否有意义,或者它是多余的。
首先,我明白在运行时,Java字符串中的字符始终表示Unicode中的符号。
其次,UTF-8编码始终能够成功地编码Unicode中的任何符号。反过来,以下代码片段将始终返回一个byte[],而不进行任何替换。getBytes文档在此处。
byte[] stringBytes = myString.getBytes(StandardCharsets.UTF_8);
然后,如果在另一个JVM实例中以以下方式使用stringBytes
,它将始终生成与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);
String
实际上是UTF-16编码的(因为char
不能容纳所有可能的Unicode代码点)。如果您想确保可以避免获取byte []
的捷径,则可以直接使用CharsetEncoder
,在其中可以配置它如何处理格式错误输入(即在发生格式错误时获得通知,而不是将其悄悄转换为替换字符)。 - Joachim Sauerchar
”。他们只说“所有char
表示某些 Unicode 代码点”,据我所知,这是正确的。暗示只能单向传递 :) - Sweeperchar
值实际上并不代表那些Unicode代码点,只包含了一半信息来找出实际引用的代码点。 - Joachim Sauer