对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/
由于
答案 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 é
”。至少我的浏览器告诉我打开文件时出现问题,并且XMLEntityScanner
显示在堆栈跟踪中。我不是XML专家,但实际上可能是HTML实体没有为XML定义吗?
编辑是的,就是这样。根据{{3}},HTML é
等实体在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都是更好的选择。