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 的文件过早结束的主要内容,如果未能解决你的问题,请参考以下文章