为什么会出现“文件过早结束”的错误?

33

我正在尝试解析一个XML响应,但失败了。最初我以为XML在响应中没有被返回,因此我通过直接链接到我的在线XML文件并编写以下代码来测试。我能够将XML打印到屏幕上而没有问题。但是当我调用我的解析方法时,我得到了文件末尾过早的错误。

如果我直接传递URL,它可以工作:

  • builder.parse("");

但当我传递InputStream时,则失败:

  • builder.parse(connection.getInputStream());

  try {
    URL url = new URL(xml);
    URLConnection uc =  url.openConnection();
    HttpURLConnection  connection = (HttpURLConnection )uc;

    connection.setDoInput(true);
    connection.setDoOutput(true);

    InputStream instream;
    InputSource source;
    //get XML from InputStream
    if(connection.getResponseCode()>= 200){
        connection.connect();       
        instream = connection.getInputStream();         
        parseDoc(instream);     
    }
    else{
        instream = connection.getErrorStream();
    }


} catch (MalformedURLException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (ParserConfigurationException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (SAXException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}



 static void parseDoc(InputStream instream) throws ParserConfigurationException,
 SAXException, IOException{


  BufferedReader buff_read = new BufferedReader(new InputStreamReader(instream,"UTF-8"));
    String  inputLine = null;

    while((inputLine = buff_read.readLine())!= null){
        System.out.println(inputLine);
    }

  DocumentBuilderFactory factory =DocumentBuilderFactory.newInstance();
  factory.isIgnoringElementContentWhitespace();
  DocumentBuilder builder = factory.newDocumentBuilder();
  Document doc = builder.parse(instream);
}

我遇到的错误:

    [Fatal Error] :1:1: Premature end of file.
org.xml.sax.SAXParseException: Premature end of file.
    at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(Unknown Source)
    at javax.xml.parsers.DocumentBuilder.parse(Unknown Source)
    at com.ameba.api.network.MainApp.parseDoc(MainApp.java:78)
    at com.ameba.api.network.MainApp.main(MainApp.java:41)

你是否有你正在尝试解析的XML文件?文件过早结束表示你的XML文件不完整,由于你在这里使用URL连接,我怀疑是网络问题。解决此问题的最佳方法是使用Wireshark或TCP监视器等工具捕获此XML文件,然后检查它是否完整。 - NiranjanBhat
@NiranjanBhat。是的,XML是完整和有效的。我已经使用直接链接解析了这个XML。似乎只有在使用InputStream时才会出现错误。 - Fabii
你为什么要进行POST请求,但没有发送任何数据? - user207421
8个回答

40

当你执行这个操作时,

while((inputLine = buff_read.readLine())!= null){
        System.out.println(inputLine);
    }

你已经读取了 instream 中的所有内容,所以现在它是空的。当你尝试执行以下操作时,

Document doc = builder.parse(instream);

你传递了一个空流,因此解析将失败。


我删除了readLine()语句。但是我仍然得到相同的错误。如果我提供直接链接到xml,它可以工作。如果我尝试使用connection.getInputStream()进行处理,它会抛出该错误。 - Fabii
还有一个问题是返回的流存在问题。问题已解决。 - Fabii
2
@Fabii,返回的流有什么问题?我想知道是什么问题,因为我也遇到了同样的问题。 - NobleUplift
4
你是正确的,你不能两次读取输入流。这里也有一个很好的解释:http://www.danielschneller.com/2008/01/saxparseexception-1-1-premature-end-of.html - lu_ko
1
@sbridges,讲解得非常好! - Baked Inhalf

6

你之所以会遇到这个错误,是因为SAXBuilder无法处理“空状态”。它会寻找至少一个<xml ..>声明,但当它收到无数据响应时,它会创建你看到的异常而不是报告空状态。


1
这个答案非常有用。如果你从第三方工具中得到错误信息,你并不总是能够调试或更改代码。我曾经遇到过完全相同的情况,其中一个本不应为空的XML实际上是空的。感谢您的帮助,我给您点赞。 - sampathsris

4

对于那些来到这篇文章寻找答案的人:

这主要是因为DOM解析器正在使用的InputStream为空

根据我遇到的情况,可能有两种情况:

  1. 您传递给解析器的InputStream已经被使用并且已经为空。
  2. File或者您创建InputStream的任何内容可能都是空文件、字符串或其他。空值可能是导致问题的原因。因此,您需要检查InputStream的来源。

1

使用inputstream时只使用一次,不要多次使用,并且执行inputstream.close()


1

我遇到了相同的错误,通过记录异常就能很容易地找出问题所在:

documentBuilder.setErrorHandler(new ErrorHandler() {
    @Override
    public void warning(SAXParseException exception) throws SAXException {
        log.warn(exception.getMessage());
    }

    @Override
    public void fatalError(SAXParseException exception) throws SAXException {
        log.error("Fatal error ", exception);
    }

    @Override
    public void error(SAXParseException exception) throws SAXException {
        log.error("Exception ", exception);
    }
});

或者,你可以用 throw 抛出错误,然后在处理条目的地方 catch 它,这样你就可以打印条目本身以更好地指示错误,而不是仅仅记录错误。


1

我通过将源Feed从http://www.news18.com/rss/politics.xml转换为https://www.news18.com/rss/politics.xml来解决了这个问题。

使用http,下面的代码会创建一个空文件,导致后续问题。

    String feedUrl = "https://www.news18.com/rss/politics.xml"; 
    File feedXmlFile = null;

    try {
    feedXmlFile =new File("C://opinionpoll/newsFeed.xml");
    FileUtils.copyURLToFile(new URL(feedUrl),feedXmlFile);


          DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
          DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
          Document doc = dBuilder.parse(feedXmlFile);

这对我来说是一个意想不到的解决方案,感谢您发布这个回复! - osoclever

0

<?xml version="1.0" encoding="UTF-8"?>

请确保在顶层正确插入标题,并且它不应指向您的 XML 文件中的任何后代。


-3
另一个原因是,你应该在mongodb设置中将你的IP地址(IPv4)加入白名单。希望能解决问题!

这个回答与作者所描述的问题完全无关。 - oneturkmen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接