如何判断从网络接收的文本/从文件读取的文本是否使用给定的编码?

时间:2015-01-25 17:01:28

标签: java character-encoding

我有一个文件,或者我从套接字读取;我读过的数据应该用给定的字符编码进行文本编码。

但是即使我指定了编码并且最终证明是错误的,操作也会成功;而不是任何类型的例外,我在文本中得到了很多:/

有没有办法可以触发失败呢?

1 个答案:

答案 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) {
    ...
}