2009-02-02 52 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文檔,並在必要時從源文件重新加載節點。