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)
);
我不会说 ?
与格式错误的字符串“等价”。
另请参阅:
目前,我需要处理 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)
);
我不会说 ?
与格式错误的字符串“等价”。
另请参阅: