请考虑以下代码:
public class ReadingTest {
public void readAndPrint(String usingEncoding) throws Exception {
ByteArrayInputStream bais = new ByteArrayInputStream(new byte[]{(byte) 0xC2, (byte) 0xB5}); // 'micro' sign UTF-8 representation
InputStreamReader isr = new InputStreamReader(bais, usingEncoding);
char[] cbuf = new char[2];
isr.read(cbuf);
System.out.println(cbuf[0]+" "+(int) cbuf[0]);
}
public static void main(String[] argv) throws Exception {
ReadingTest w = new ReadingTest();
w.readAndPrint("UTF-8");
w.readAndPrint("US-ASCII");
}
}
观察输出:
µ 181
? 65533
为什么readAndPrint()
(使用US-ASCII的那个)的第二次调用成功?我希望它会抛出一个错误,因为输入不是这个编码中的正确字符。 Java API或JLS中强制执行此行为的地方是什么?
答案 0 :(得分:9)
在输入流中查找不可解码的字节时的默认操作是用Unicode字符U+FFFD REPLACEMENT CHARACTER替换它们。
如果您想更改它,可以传递CharacterDecoder
to the InputStreamReader
,其CodingErrorAction
配置不同:
CharsetDecoder decoder = Charset.forName(usingEncoding).newDecoder();
decoder.onMalformedInput(CodingErrorAction.REPORT);
InputStreamReader isr = new InputStreamReader(bais, decoder);
答案 1 :(得分:3)
我会说,这与构造函数相同
String(byte bytes[], int offset, int length, Charset charset)
:
此方法始终使用此charset的默认替换字符串替换格式错误的输入和不可映射的字符序列。当需要更多地控制解码过程时,应该使用java.nio.charset.CharsetDecoder类。
使用CharsetDecoder
,您可以指定其他CodingErrorAction
。