为什么java.lang.String不验证编码?

时间:2016-10-10 06:13:41

标签: java utf-8 decoding

我跑进了让我感到惊讶的事情。当尝试从不正确的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安全的来源。

1 个答案:

答案 0 :(得分:1)

String(byte[], String)的Java文档说:

  

当给定字节无效时,此构造函数的行为   给定的字符集未指定。 CharsetDecoder类应该是   当需要更多地控制解码过程时使用。

Thee构造函数String(byte[], Charset)还有另一种行为:

  

此方法始终替换malformed-input和unmappable-character   具有此charset的默认替换字符串的序列。该   当更多控制时,应该使用CharsetDecoder类   解码过程是必需的。

我更喜欢Phython的行为。但你不能指望Java与Python完全一样。