我有一个文件,或者我从套接字读取;我读过的数据应该用给定的字符编码进行文本编码。
但是即使我指定了编码并且最终证明是错误的,操作也会成功;而不是任何类型的例外,我在文本中得到了很多�
:/
有没有办法可以触发失败呢?
答案 0 :(得分:5)
是的。
首先,一些信息:那个讨厌的�
字符到底是什么?好吧,它是Unicode's "replacement character", code point U+FFFD。
现在,你为什么这样做?为了解释这一点,我们需要深入研究发生的事情......
首先,"正式"定义:字符编码是一个定义字节流和字符流之间的双射的过程;因为它是一个双射,它意味着定义了两个操作:编码(将字符流转换为字节流)和解码(将字节流转换为字符流)。
在Java中,字符编码包含在Charset
中;您可以使用Charset.newEncoder()
获取编码器,使用Charset.newDecoder()
获取解码器。
当然,可能会发生在解码过程中,这里感兴趣的是,某个字节序列结果是格式错误,在这种情况下CharsetDecoder
必须决定做什么。 ..这种行为取决于CodingErrorAction
,它有三个值:
REPLACE
(默认值!! ):用Unicode的替换字符替换任何不可映射的序列!IGNORE
:废弃所有无法映射的序列,不输出任何内容; REPORT
:在不可映射的序列上抛出异常...... 现在,我们想要检测格式错误的输入并抛出错误是REPORT
他们!
那么,鉴于InputStream
,我们该如何做?解决方案是使用InputStreamReader
; it has a constructor allowing you to specify a CharsetDecoder
as an argument。您所要做的就是创建解码器!
例如,如果您想确保正确的UTF-8,您可以这样做:
final CharsetDecoder decoder = StandardCharsets.UTF_8
.newDecoder().onMalformedInput(CodingErrorAction.REPORT);
try (
final InputStreamReader reader = new InputStreamReader(in, decoder);
) {
// read from the reader here
}
您想要捕获的例外是CharacterCodingException
。请注意,它会继承IOException
,因此您需要:
try (
...
) {
...
} catch (CharacterCodingException e) {
...
} catch (IOException e) {
...
}