我正在尝试在java中解析高达500 MB的XML文件。我试图使用SAX,但它给了我这个错误 java.lang.OutOfMemoryError:Java堆空间 at com.sun.org.apache.xerces.internal.util.XMLStringBuffer.append(Unknown Source) 你能帮助我吗? 非常感谢。 附:较小的XML文件可以正常工作
答案 0 :(得分:11)
您很可能没有正确使用SAX,或者您的应用程序不适合流处理。
SAX的重点是避免将整个XML结构保留在内存中,但只有在不保留大量上下文的情况下才能以小块的形式处理XML,并且处理结果要小于已处理的XML(因此它不会使用太多内存)或者本身可以传递给收件人或连续写入磁盘。
编辑:您也可能只是内存泄漏,即您正在查看不再需要的数据,从而阻止其收集垃圾。如果您使用任何列表,地图或集来处理XML,请确保在开始下一个块之前删除处理一个XML块时添加的任何内容。
答案 1 :(得分:5)
尝试使用Streaming API for XML(java6中的新增功能) 它为此做了
http://www.javabeat.net/articles/14-java-60-features-part-2-pluggable-annotation-proce-2.html
答案 2 :(得分:3)
您可以通过指定例如
来尝试增加Java堆大小java -Xmx1024M MyClass
命令行上的(或任何值适合您的文档大小)。
答案 3 :(得分:2)
StAX for Java版本6之前版本: http://stax.codehaus.org/
答案 4 :(得分:1)
假设您有以下XML结构:
<?xml version="1.0"?>
<list>
<item>
<name>Alpha</name>
<age>10</age>
</item>
<item>
<name>Beta</name>
<age>20</age>
</item>
<!-- many many items -->
</list>
并且您希望获得所有&lt; item&gt; s
公共类项目 { 字符串名称; 字符串年龄; }
您的SAX处理程序将如下所示
public class MyHandler extends DefaultHandler
{
Item current=null;
StringBuilder content=null;
@Override
public void startElement(String uri, String localName, String name,
Attributes attributes) throws SAXException {
if( name.equals("item")
{
current= new Item();
}
else if(name.equals("name") || name.equals("age"))
{
content= new StringBuilder();
}
}
@Override
public void endElement(String uri, String localName, String name)
throws SAXException
{
if(name.equals("item"))
{
//DO SOMETHING WITH current
System.out.println(current);
current=null;
}
else if(name.equals("name"))
{
current.name= content.toString();
}
else if(name.equals("age"))
{
current.age= content.toString();
}
content=null;
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
if(content!=null)
{
content.append(ch,start,length);
}
}
}
正如您所看到的,“内容”仅存储在“年龄”和“名称”标签之间。
答案 5 :(得分:1)
您可能需要查看ScaleDOM,它允许解析非常大的XML文件:https://github.com/whummer/scaleDOM
由于XML节点的延迟加载,ScaleDOM的内存占用量很小。它只将XML文档的一部分保留在内存中,并在必要时从源文件重新加载节点。
答案 6 :(得分:0)
看看Apache Digester。