我跑进了让我感到惊讶的事情。当尝试从不正确的utf-8字节构建字符串时,String构造函数仍然给我一个结果。没有异常被抛出。例如:
byte[] x = { (byte) 0xf0, (byte) 0xab };
new String(x, "UTF-8"); // This works, or at least gives a result
// This however, throws java.nio.charset.MalformedInputException: Input length = 3
ByteBuffer wrapped = ByteBuffer.wrap(x);
CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder();
decoder.decode(wrapped);
在例如python中尝试相同的操作也会产生错误,错误消息会更加清晰:
>>> '\xf0\xab'.decode('utf-8')
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "/usr/lib/python2.7/encodings/utf_8.py", line 16, in decode
return codecs.utf_8_decode(input, errors, True)
UnicodeDecodeError: 'utf8' codec can't decode bytes in position 0-1: unexpected end of data
那么为什么java字符串构造函数似乎忽略了输入中的错误?
更新:我应该更清楚一点。 javadoc指出这是未指定的。但是这样做的原因是什么呢?在我看来,你永远不会想要这种行为,任何时候你都不能100%确定你需要使用CharsetDecoder安全的来源。
答案 0 :(得分:1)
String(byte[], String)的Java文档说:
当给定字节无效时,此构造函数的行为 给定的字符集未指定。 CharsetDecoder类应该是 当需要更多地控制解码过程时使用。
Thee构造函数String(byte[], Charset)还有另一种行为:
此方法始终替换malformed-input和unmappable-character 具有此charset的默认替换字符串的序列。该 当更多控制时,应该使用CharsetDecoder类 解码过程是必需的。
我更喜欢Phython的行为。但你不能指望Java与Python完全一样。