SAX 在以下异常中不断死亡:
Invalid byte 2 of 3-byte UTF-8 sequence
问题在于它大部分是正确的 UTF-8 编码,但其中有一些错误。我们无法获得该文件的新版本,我们必须使用该文件。
那么我们如何告诉 SAX 忽略无效的字符序列,或者清理 UTF-8 文件以使其没有无效的 UTF-8 序列?
您可以在 SAX 读取流之前对其进行过滤。创建一个 InputStream 读取您的流并删除无效字符。
我建议您将文件清理为与将其解析为 XML完全不同的步骤。
UTF-8 是一种相当容易理解的编码;这个网页显示了 UTF-8 是如何形成的。我建议您编写一个程序来读取您的输入文件并写出一个新文件。它将一个字节一个字节地读取,只有当它看到它已经被有效地形成时才写出一个字符。当它看到一个无效字节时,它会写出字符串“UTF8ERROR”或其他一些不会在输入数据中自然出现的容易找到的标记。然后它会跳过角色的其余部分。
之后,您可以检查错误发生的位置并修复数据......然后正常解析它。
通过这种方式,您将看到错误的广泛性,看看它们是否有任何模式,并有可能纠正它们。如果您要从同一来源收到更多数据,我强烈建议您告诉他们这个问题......这可能表明他们方面存在更严重的问题。
SAX(和其他 XML 工具)旨在处理格式良好(或在需要时有效)的 XML。当输入格式不正确(包括未能符合编码)时,它们会故意抛出错误或异常。因此,正如其他答案所建议的那样,您必须使用单独的步骤来清理输入。
(类似地,SAX 会抛出格式不正确的 XML 的 HTML 错误,例如缺少结束标记)。
我想这对你没有多大帮助,但也许其他人想知道:
我最近在检索带有 ISO-8859-1 标头的 UTF-8 XML 文件时遇到了同样的异常。解决方案是通过 String.getBytes(charset) 手动指定 UTF-8:
public Document parseRequest(HttpServletRequest request) {
DocumentBuilderFactory builder = DocumentBuilderFactory.newInstance();
DataInputStream dataStream = new DataInputStream(request.getInputStream());
String xml = dataStream.readUTF();
ByteArrayInputStream byteStream = new ByteArrayInputStream(xml.getBytes("UTF-8"));
return builder.newDocumentBuilder().parse(byteStream);
}
编辑:..甚至更简单:
public Document parseRequest(HttpServletRequest request) {
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
Reader reader = new InputStreamReader(request.getInputStream(), "UTF-8");
InputSource source = new InputSource(reader);
return domFactory.newDocumentBuilder().parse(source);
}
你能用某种方式 java.nio.charset.CharsetDecoder
一起使用吗?InputStreamReader(InputStream in, CharsetDecoder dec)
如何处理解码错误取决于为该类型错误请求的操作,该操作由 CodingErrorAction 类的实例描述。可能的错误动作是忽略错误输入,通过返回的 CoderResult 对象向调用者报告错误,或者用替换字符串的当前值替换错误输入。替换具有初始值“\uFFFD”;它的值可以通过 replaceWith 方法更改。
(来自CharsetDecoder
javadoc)