验证XML文档会导致"1字节UTF-8序列的无效字节1".

Pop*_*ops 5 java xml saxon schematron

我正在使用Probatron4j验证一些针对Schematron样式表的XML文件,Probatron4j在内部使用Saxon.大多数情况下,这工作正常,但偶尔,处理崩溃与错误

org.xml.sax.SAXParseException:1字节UTF-8序列的无效字节1.

我的研究表明,这条消息通常表明(没有特别的顺序)

  • 公然无效的数据(例如,尝试读取ZIP文件,就像它是XML文件一样);
  • 字节顺序标记的存在;
  • 在UTF-8中存在不合法的字符; 要么
  • 声称是UTF-8编码的文件.

这些都不适用于我正在处理的文件.我在程序执行期间检查了字节数组形式的输入,它不包含BOM或任何非ASCII字符.

处理通过我的30kb文档的大约五分之一,然后崩溃在一个不起眼的英语句子上("不起眼",我的意思是所有字节都在32(空格)和122(小写z)之间;换句话说,标准键盘字符).假定有问题的元素的字节在这篇文章的末尾.

奇怪的是,失败的文档是通过从较大的文档中删除一些元素来生成的,这些元素被相同的代码干净地处理.

我知道异常是在parse(InputSource input)实现org.xml.saxXMLReader接口的对象的方法中引发的.根据Javadoc,SAXException表示

任何SAX异常,可能包含另一个异常.

检查调试器中的异常表明没有包装异常.

可能导致此错误的原因是什么?

编辑:

[60, 80, 97, 114, 97, 103, 114, 97, 112, 104, 62, 69, 120, 101, 99, 117, 116,
 105, 118, 101, 32, 83, 117, 109, 109, 97, 114, 121, 58, 32, 70, 114, 111, 109,
 32, 49, 55, 53, 52, 32, 116, 111, 32, 49, 55, 54, 51, 13, 10, 32, 32, 32, 32,
 32, 32, 32, 32, 32, 32, 32, 32, 69, 117, 114, 111, 112, 101, 32, 97, 110, 100,
 32, 116, 104, 101, 32, 65, 109, 101, 114, 105, 99, 97, 115, 32, 119, 101, 114,
 101, 32, 99, 97, 117, 103, 104, 116, 32, 117, 112, 32, 105, 110, 32, 97, 32, 99,
 111, 110, 102, 108, 105, 99, 116, 32, 98, 101, 116, 119, 101, 101, 110, 32, 69,
 110, 103, 108, 97, 110, 100, 44, 32, 117, 110, 100, 101, 114, 32, 75, 105, 110,
 103, 32, 71, 101, 111, 114, 103, 101, 32, 73, 73, 44, 32, 97, 110, 100, 32, 70,
 114, 97, 110, 99, 101, 44, 32, 117, 110, 100, 101, 114, 32, 75, 105, 110, 103,
 32, 76, 111, 117, 105, 115, 32, 88, 86, 46, 32, 73, 110, 32, 69, 117, 114, 111,
 112, 101, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 116, 104, 105,
 115, 32, 112, 101, 114, 105, 111, 100, 32, 119, 97, 115, 32, 107, 110, 111, 119,
 110, 32, 97, 115, 32, 116, 104, 101, 32, 83, 101, 118, 101, 110, 32, 89, 101,
 97, 114, 115, 39, 32, 87, 97, 114, 59, 32, 105, 110, 32, 78, 111, 114, 116, 104,
 32, 65, 109, 101, 114, 105, 99, 97, 32, 105, 116, 32, 99, 97, 109, 101, 32, 116,
 111, 32, 98, 101, 32, 99, 97, 108, 108, 101, 100, 32, 116, 104, 101, 32, 70,
 114, 101, 110, 99, 104, 32, 97, 110, 100, 32, 73, 110, 100, 105, 97, 110, 32,
 87, 97, 114, 46, 32, 73, 116, 32, 119, 97, 115, 32, 97, 32, 99, 111, 110, 102,
 108, 105, 99, 116, 32, 111, 118, 101, 114, 13, 10, 32, 32, 32, 32, 32, 32, 32,
 32, 32, 32, 32, 32, 116, 114, 97, 100, 101, 32, 97, 110, 100, 32, 108, 97, 110,
 100, 46, 60, 47, 80, 97, 114, 97, 103, 114, 97, 112, 104, 62]
Run Code Online (Sandbox Code Playgroud)

在第三次出现之后抛出异常109.

Pop*_*ops 4

我已经解决了这个问题。即使 Java 在其String对象内部使用 UTF-8,String类的getBytes()方法也会以系统默认编码生成字节,除非您明确指定需要 UTF-8(或它理解的其他编码方案)。

我不完全确定这是如何或为什么解决问题的,因为抛出异常的位置附近的字节(问题末尾的字节)本身都是有效的 UTF-8 字节,但看起来确实如此拥有固定的东西。

我能想到的唯一潜在原因是我错过了文件中较早的一个无效字节,该字节把事情搞砸了,但并没有立即导致崩溃。我正在从 a 读取字节ByteArrayInputStream,因此程序可能会同时从缓冲区读取一大块,这会将标记设置pos到超出假设的坏字符所在位置的位置。