org.xml.sax.SAXParseException:*VALID* XML 的文件过早结束

Posted

技术标签:

【中文标题】org.xml.sax.SAXParseException:*VALID* XML 的文件过早结束【英文标题】:org.xml.sax.SAXParseException: Premature end of file for *VALID* XML 【发布时间】:2012-06-22 07:13:19 【问题描述】:

我越来越奇怪“文件过早结束”。最近几天在我们的一台服务器上例外。 same 配置 XML 在另一台服务器上工作正常。我们在这两台服务器上都使用 Tomcat 5.0.28。这段代码已经工作了很长时间(7 年以上),只是在最近的服务器崩溃之后,我们在其中一台服务器上遇到了这个问题。 XML 和 Java 解析代码没有变化。 :(

我能看到的唯一区别是 Java 版本 -

问题服务器 java版本“1.6.0_16” Java(TM) SE 运行时环境 (build 1.6.0_16-b01) Java HotSpot(TM) 64 位服务器 VM(内部版本 14.2-b01,混合模式)

工作服务器 java版本“1.6.0_07” Java(TM) SE 运行时环境 (build 1.6.0_07-b06) Java HotSpot(TM) 64 位服务器 VM(内部版本 10.0-b23,混合模式)

这是已经工作了几年的 Java 代码 -

private void readSource(final InputSource in ) 
    try 
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document doc = db.parse(in);
        Element elt = doc.getDocumentElement();

        this.readElement( elt );
     catch ( Exception ex ) 
        ex.printStackTrace();
        throw new ConfigurationException( "Unable to parse configuration information", ex );
    

这里是个例外。

[Fatal Error] :-1:-1: Premature end of file.
org.xml.sax.SAXParseException: Premature end of file.
        at org.apache.xerces.parsers.DOMParser.parse(Unknown Source)
        at org.apache.xerces.jaxp.DocumentBuilderImpl.parse(Unknown Source)
        at com.circus.core.Configuration.readSource(Configuration.java:706)

我已经尝试过验证 XML 并没有发现任何错误。知道我还能在哪里寻找可能的问题吗?

任何指针将不胜感激!

TIA, - 马尼什

【问题讨论】:

1. InputSource 是如何构建的? 2.XML有多大? 3. XML 是否来自本地文件,来自 URL、数据库、其他流式源 - 可能是套接字断开连接,或者 InputStream 在解析过程中关闭? 您确定服务器崩溃时没有添加一些特殊字符吗?您可以尝试从您的一台工作服务器中输入 XML,看看它是否有效。 @npe - (1) InputSource 使用 FileReader - this.readSource( new InputSource( fr ) ); (2) XML 大小为 108.1 KB。现在已经有很长时间了。 (3) XML 来自本地文件系统。我还怀疑InputStream 是否在两者之间关闭。我怎样才能检测到呢?再一次,想知道为什么它以前有效而不是现在 :( @npinti - 我使用了来自 SVN 的新 XML,并在 XML 验证器中尝试了相同的版本。它有效的 XML。 @Manish:尝试在FileReader#close() 中设置一个断点,看看它是否被调用了。或者子类 FileReader 并添加一些日志记录 - 例如,您可以转储 read() 的字节以查看文件是否已完全读取,或者它在某处中断。 @Manish:另一个问题:InputSource 是重复使用的,还是总是从头开始创建的? 【参考方案1】:

这是Java InputStream 的问题。当文件偏移位置计数器移动到文件末尾时读取流时。在随后使用相同的流读取时,您将收到此错误。因此,您必须关闭并再次重新打开流或调用inputStream.reset() 将偏移计数器重置为其初始位置。

【讨论】:

这描述了我的问题。我使用了 inputStream 两次。但是,reset() 不起作用。那么,如何关闭并重新打开输入流?【参考方案2】:

已解决。问题出在其他地方。 cron 作业中的另一个代码是将 XML 截断为长度为 0 的文件。我已经处理好了。

【讨论】:

这解决了我在解决 android 分支上的冲突后遇到的问题。如果你有一个 0 字节的 xml 文件,资源将不会成功捆绑。如果您运行find . -type f -empty | grep xml 来查找有问题的文件并将其删除,此错误就会消失。【参考方案3】:

只有在解析空字符串/空字节数组时才会发生此异常。

下面是关于如何重现它的 sn-p:

String xml = ""; // <-- deliberately an empty string.
ByteArrayInputStream xmlStream = new java.io.ByteArrayInputStream(xml.getBytes());
Unmarshaller u = JAXBContext.newInstance(...)
u.setSchema(...);
u.unmarshal( xmlStream ); // <-- here it will fail

【讨论】:

【参考方案4】:

在解析之前,请确保您没有在任何地方使用您的 inputstream。示例代码如下: 下面的响应是httpresponse(即响应),主要内容包含在StringEntity (i.e. getEntity())in form of inputStream(i.e. getContent()) 中。

InputStream rescontent = response.getEntity().getContent();
tsResponse=(TsResponse) transformer.convertFromXMLToObject(rescontent );

【讨论】:

【参考方案5】:

如果输入流未正确关闭,则可能会发生此异常。 确保 : 如果使用的输入流没有以某种方式使用“之前”,那么您打算阅读的地方。 即,如果在单个操作中从同一输入流中第二次读取,则第二次调用将得到此异常。 还要确保在 finally 块中关闭输入流或类似的东西。

【讨论】:

【参考方案6】:

您确定 XML 文件的字符编码正确吗? FileReader 始终使用平台默认编码,因此如果“工作”服务器的默认编码为(例如)ISO-8859-1,而“问题”服务器使用 UTF-8,如果 XML 包含任何非 ASCII 字符。

如果您从 FileInputStream 而不是 FileReader 创建 InputSource 是否有效?

【讨论】:

【参考方案7】:

2021 年 12 月 6 日再次出现同样的错误!!!

示例跟踪:

XmlBeanDefinitionStoreException: Line -1 in XML document from ServletContext resource [<here a reference to spring context .xml file>] is invalid; nested exception is org.xml.sax.SAXParseException; Premature end of file.
Caused by: org.xml.sax.SAXParseException; Premature end of file.
at org.apache.xerces.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:201)
at org.apache.xerces.util.ErrorHandlerWrapper.fatalError(ErrorHandlerWrapper.java:175)
at org.apache.xerces.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:398)
at org.apache.xerces.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:325)
at org.apache.xerces.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:282)
at org.apache.xerces.impl.XMLVersionDetector.determineDocVersion(XMLVersionDetector.java:204)
at org.apache.xerces.impl.xs.opti.SchemaParsingConfig.parse(SchemaParsingConfig.java:576)
at org.apache.xerces.impl.xs.opti.SchemaParsingConfig.parse(SchemaParsingConfig.java:679)
at org.apache.xerces.impl.xs.opti.SchemaDOMParser.parse(SchemaDOMParser.java:527)
at org.apache.xerces.impl.xs.traversers.XSDHandler.getSchemaDocument(XSDHandler.java:2148)
at org.apache.xerces.impl.xs.traversers.XSDHandler.parseSchema(XSDHandler.java:557)

提示:

    Apache CAMEL 团队决定重新组织 CAMEL 模式文件,例如通常在 XML Spring 上下文中引用。 他们不只是删除(这将需要一个简单的例外,很容易发现)http://camel.apache.org/schema/spring/camel-spring-2.16.4.xsd 通常的架构位置,而是实现了对 HTTPS 的 HTTP 301 重定向响应。

    Apache XERCES 库在 HTTP 301 的情况下不会引发错误,但假定它已收到一个空文件!这需要奇怪和错误的异常/将您置于错误的轨道上,因为它们报告链接到*** XML 文件的故障,而不是实际有问题的架构描述符

    在我们的应用服务器平台中,在 WAR 重新加载/部署时(来自数据/内容 repo 缓存)对所有模式描述符及其 XSD 依赖项的完全重新验证是完全出乎意料的......而且完全没用!更糟糕的是:创建运行时公共网络依赖项,仅用于重新加载已验证的组件和描述符(在构建时)

1+2+3 以上,砰! 主要服务中断:生产服务器无法重新加载依赖于 CAMEL 的任何组件

修正:

两名候选人:

a) 在 XML 中的 xsi:schemaLocation 属性中,只需将“s”添加到 http://camel.apache.org/schema/etc 成为 https://.... 但接受对每个组件重新加载的公共网络依赖项

b) 用 classpath: 替换所有 http://... shema 位置。您将下载所有 XSD 和子依赖模式,并将它们与 WAR 一起部署,以确保对类加载器的可见性。例如。将文件放入 java/main/resources/somename.xsd 并提供 classpath:somename.xsd 作为模式位置路径

【讨论】:

【参考方案8】:

在我们的例子中,它是一个空的 AndroidManifest.xml

在升级 Eclispe 时,我们遇到了 usual trouble,而且 AndroidManifest.xml 必须在被破坏后被构建脚本签入到 SVN。

通过从 Eclipse 内部编译而不是从命令行找到它。

【讨论】:

以上是关于org.xml.sax.SAXParseException:*VALID* XML 的文件过早结束的主要内容,如果未能解决你的问题,请参考以下文章