2009-02-02 13 views
2

我正试图解析一个XML文件高达500 MB的Java。我试图使用SAX,但它给了我这个错误 java.lang.OutOfMemoryError:Java堆空间 在com.sun.org.apache.xerces.internal.util.XMLStringBuffer.append(未知源) 你能帮我吗? 非常感谢。 P.S.较小的XML文件,使用工作流API为XML就好Big XML文件和OutOfMemoryError

+0

我对500MB xml文件中存储的内容感兴趣! – 2009-02-02 20:24:45

+0

你的XML是否包含非常大的文本(数百万字符,比如说)而不包含中介元素? – bendin 2009-02-02 20:39:17

回答

3

您可以尝试通过指定例如增加Java堆大小就

java -Xmx1024M MyClass 

在命令行(或什么价值将适合您的文档大小)。

11

很可能您没有正确使用SAX,或者您的应用程序不适合流处理。

SAX的重点在于避免将整个XML结构保留在内存中,但这只有在您可以在不保留很多上下文的情况下以小块处理XML并且处理结果远小于处理过的XML(因此它不会使用太多的内存),或者本身可以传递给收件人或连续写入磁盘。

编辑:也有可能你只是有内存泄漏,即你坚持不再需要的数据,防止它被垃圾收集。如果使用任何列表,映射或集合来处理XML,请确保在开始下一个块之前删除在处理一个XML块时添加到它们的任何内容。

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> 

而且你想获得的所有<项目>小号

公共类Item { String name; 弦乐年龄; }

你的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); 
        } 
      } 

} 

正如你所看到的,“内容”只记住了“年龄”和“名称”标签之间。

1

你可能想看看ScaleDOM,这使得解析非常大的XML文件:https://github.com/whummer/scaleDOM

ScaleDOM有一个小的内存占用,由于XML节点的延迟加载。它只保留内存中的一部分XML文档,并在必要时从源文件重新加载节点。