RE:大XML文件

时间:2009-02-03 20:59:14

标签: java xml memory sax

Big XML File的跟进问题:

首先非常感谢你的回答。 之后......我做错了什么? 这是我的使用SAX的课程:

public class SAXParserXML extends DefaultHandler {
  public static void ParcourXML() {

      DefaultHandler handler = new SAXParserXML();
      SAXParserFactory factory = SAXParserFactory.newInstance();
      try {
          String URI = "dblp.xml";
          SAXParser saxParser = factory.newSAXParser();
          saxParser.parse(URI,handler);
      } catch (Throwable t) {
     t.printStackTrace ();
       }
  }



  public void startElement (String namespaceURI,String simpleName,String qualifiedName,Attributes attrs) throws SAXException {
  }
  public void endElement (String namespaceURI,String simpleName,String qualifiedName) throws SAXException {

  }
}

你可以看到我对我的XML文件什么都不做,但是它给出了这个错误:

java.lang.OutOfMemoryError: Java heap space
    at com.sun.org.apache.xerces.internal.util.XMLStringBuffer.append(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.refresh(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.invokeListeners(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.peekChar(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
    at javax.xml.parsers.SAXParser.parse(Unknown Source)
    at javax.xml.parsers.SAXParser.parse(Unknown Source)
    at SAXParserXML.ParcourXML(SAXParserXML.java:30)
    at Main.main(Main.java:28)

我也试过Stax ......同样的错误......我该怎么办? 此外,我将Java堆大小增加到1260M

java -Xmx1260M SAXParserXML

XML文件具有以下形式:

<dblp> 
   <incollection> 
      <author>... </author> 
      .... 
      <author>... </author> 
      #other tags-i'm interested only by <author>#
      ... 
   </incollection> 
   <incollection> 
   # the same thing# 
   </incollection> 
   .... 
</dblp> 

您可以找到原始文件:http://dblp.uni-trier.de/xml/

由于

5 个答案:

答案 0 :(得分:6)

Java 1.6有一个bug,它显示了完全相同的堆栈跟踪,并且它现在已经不固定了。较新的Xerces版本似乎没问题。

对于那些仍然包含大量结构的大型文档,您可以考虑使用pull-parsing,即解析部分结构,例如使用StAX

答案 1 :(得分:2)

嗯,给定:

public class Main {

    /**
     * @param args the command line arguments
     */
    public static void main(String argv[]) {
        Writer out;

        // Use an instance of ourselves as the SAX event handler
        Echo handler = new Echo();
        // Use the default (non-validating) parser
        SAXParserFactory factory = SAXParserFactory.newInstance();
        try {
            // Set up output stream
            out = new OutputStreamWriter(System.out, "UTF8");
            // Parse the input 
            SAXParser saxParser = factory.newSAXParser();
            saxParser.parse(new File("/tmp/dblp.xml"), handler);
        } catch (Throwable t) {
            t.printStackTrace();
        }
        System.out.println("Incollections = " + handler.cnt);
        System.exit(0);
    }

    static class Echo extends DefaultHandler {
        public int cnt = 0;
        @Override
        public void startElement(String namespaceURI,
                String sName, // simple name
                String qName, // qualified name
                Attributes attrs)
                throws SAXException {
            if (qName.equals("incollection")) {
                cnt = cnt + 1;
            }
        }
    }
}

这适用于Java 5,但我确实在Java 6下获得了OOM。

我这样运行:

java -DentityExpansLimit=512000 -jar xmltest.jar

它打印出来:

Incollections = 8353

哪个方便:

grep "<incollection" /tmp/dblp.xml | wc -l
8353

所以,仅供参考,数据点等

答案 2 :(得分:0)

您的代码中似乎存在HTML entites的问题,即第一个块中的“Jos &eacute;”。至少我的浏览器告诉我打开文件时出现问题,并且XMLEntityScanner显示在堆栈跟踪中。我不是XML专家,但实际上可能是HTML实体没有为XML定义吗?

编辑是的,就是这样。根据{{​​3}},HTML &eacute;等实体在HTML DTD中定义; XML只有非常少量的预定义实体。

答案 3 :(得分:0)

我不知道正确的术语,但你的XML有多“深入”?例如,示例中的“author”标记是2个元素深度。如果你的标签真的非常深,那么这就是为什么你有内存问题?

答案 4 :(得分:0)

听起来像XML文件中的一个文本段(或CDATA,处理指令或注释)非常长,并且解析器不会将其拆分为多个段。 或者可能是解析器无法正确解析DOCTYPE声明:如果是这样,它可能会尝试读取所有xml内容,就像它是DTD子集的一部分一样。

但这只是猜测。你提到你试过Stax:哪个实现? JDK 1.6附带Sun Sjsxp。但你也可以试试Woodstox(http://woodstox.codehaus.org),它经常以更强大的方式处理事情。 因此,如果您不使用Woodstox,您可以看到会发生什么。它会将文本段拆分为较小的块,除非您强制文本合并(非默认)。

哦,以防你使用Stax参考实现(http://stax.codehaus.org)进行测试;不幸的是,它已经非常多了。这可能会导致问题。  使用Stax,Sjsxp和Woodstox都是更好的选择。