2009-02-03 53 views
5

后续问题到Big XML FileRE:大XML文件

首先非常感谢您的回答。 ......我做错了什么? 这是我的类,它使用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) 

我也试过斯塔克斯......同样的错误......什么我可不可以做? 我也增加了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/

感谢

+0

如果您告诉我们更多关于您正在解析的XML类型,这将有所帮助。 – 2009-02-03 21:03:00

回答

6

有一个用于Java 1.6的bug,它显示了完全相同的堆栈跟踪,它现在是不固定的。较新的Xerces版本似乎很好。

对于文件这么大,仍然包含相当数量的结构,您可以考虑使用拉解析,即解析部分结构,例如StAX

+0

我已经尝试过Stax ...它给出了相同的错误 – user61652 2009-02-03 21:36:09

+0

如果它给出了相同的堆栈跟踪,那么您没有使用StAX。什么是StAX的堆栈跟踪? – lavinio 2009-11-11 20:38:06

+0

我想我和主题首发者有同样的问题。该错误页面指出该错误已关闭......但它真的修复了吗?我在Windows XP上使用JDK 6 Update 23。 – 2010-12-14 15:27:26

0

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

编辑是的,就是这样。根据Wikipedia,在HTML DTD中定义了像&eacute;这样的实体; XML只有极少数的预定义实体。

+0

所有实体都在dblp.dtd中定义 – user61652 2009-02-03 21:34:48

0

我不知道这个正确的术语,但你的XML到底有多“深”?例如,你的例子中的“author”标签是2个元素深的。如果你的标签真的很深,也许这就是为什么你有内存问题?

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下的OOM 6

我运行它是这样的:

java -DentityExpansLimit=512000 -jar xmltest.jar 

它打印:

Incollections = 8353 

哪个方便:

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

那么,FYI,数据点等

0

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

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

哦,以防万一您正在使用Stax参考实现(http://stax.codehaus.org)进行测试;不幸的是,它是非常有问题的。所以这可能会导致问题。 Sjsxp和Woodstox在Stax方面都是更好的选择。