如何检测非法的UTF-8字节序列以在java输入流中替换它们?

有问题的文件不在我的控制之下。 大多数字节序列都是有效的UTF-8,它不是ISO-8859-1(或其他编码)。 我想尽我所能提取尽可能多的信息。

该文件包含一些非法字节序列,应替换为替换字符。

这不是一件容易的事,它认为它需要一些关于UTF-8状态机的知识。

Oracle有一个包装器可以满足我的需求:
UTF8ValidationFilter javadoc

是否有类似的东西(商业或免费软件)?

谢谢
-stephan

解:

final BufferedInputStream in = new BufferedInputStream(istream); final CharsetDecoder charsetDecoder = StandardCharsets.UTF_8.newDecoder(); charsetDecoder.onMalformedInput(CodingErrorAction.REPLACE); charsetDecoder.onUnmappableCharacter(CodingErrorAction.REPLACE); final Reader inputReader = new InputStreamReader(in, charsetDecoder); 

java.nio.charset.CharsetDecoder做你需要的。 此类为不同类型的错误提供了用户可定义的onMalformedInput()解码(请参阅onMalformedInput()onUnmappableCharacter() )。

CharsetDecoder写入一个OutputStream ,您可以使用java.io.PipedOutputStream将其传递到InputStream ,从而有效地创建一个过滤的InputStream

一种方法是读取前几个字节以检查字节顺序标记(如果存在)。 有关BOM的更多信息: http : //en.wikipedia.org/wiki/Byte_order_mark在给定的URL中,您将找到BOM字节的表。 但是,一个问题是,UTF-8不需要在其标题中使用BOM。 解决问题的另一种方法是通过模式识别(每次读取几个字节-8位)。 无论如何,这是一个复杂的解决方案..

您想要的行为已经是InputStreamReader的默认行为。 所以没有必要自己指定它。 这足以:

 final BufferedInputStream in = new BufferedInputStream(istream); final Reader inputReader = new InputStreamReader(in, StandardCharsets.UTF_8);