【问题标题】:Big XML file and OutOfMemoryError大 XML 文件和 OutOfMemoryError
【发布时间】:2010-10-05 00:27:29
【问题描述】:

我正在尝试在 java 中解析一个最大为 500 mb 的 XML 文件。我尝试使用 SAX,但它给了我这个错误 java.lang.OutOfMemoryError:Java 堆空间 在 com.sun.org.apache.xerces.internal.util.XMLStringBuffer.append(未知来源) 你能帮助我吗? 非常感谢。 附:较小的 XML 文件也能正常工作

【问题讨论】:

  • 我也对您在 500MB xml 文件中存储的内容感兴趣!?
  • 您的 XML 是否包含非常大的(例如,数千万个字符)文本运行而没有干预元素?
  • 我不知道为什么……是一个学校项目。文件在这里dblp.uni-trier.de/xml

标签: java xml memory parsing out-of-memory


【解决方案1】:

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

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

编辑:您也可能只是发生了内存泄漏,即您保留了不再需要的数据,从而阻止了垃圾收集。如果您使用任何列表、映射或集合来处理 XML,请确保在处理一个 XML 块时添加到它们的任何内容在开始下一个块之前都已删除。

【讨论】:

  • 绝对正确。我可以用 SAX 解析超过 2GB 的 XML 文件。
【解决方案2】:

尝试使用 XML 的 Streaming API(java6 中的新功能) 它是为此而生的

http://www.javabeat.net/articles/14-java-60-features-part-2-pluggable-annotation-proce-2.html

【讨论】:

    【解决方案3】:

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

    java -Xmx1024M MyClass
    

    在命令行上(或任何适合您文档大小的值)。

    【讨论】:

      【解决方案4】:

      StAX for Java 6 之前的版本: http://stax.codehaus.org/

      【讨论】:

        【解决方案5】:

        您可能想查看 ScaleDOM,它允许解析非常大的 XML 文件:https://github.com/whummer/scaleDOM

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

        【讨论】:

          【解决方案6】:

          假设您有以下 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>
          

          你想得到所有的

          public class Item
          {
              String name;
              String age;
          }
          

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

          如您所见,content 仅记忆在 agename 标记之间。

          【讨论】:

            【解决方案7】:

            看看 Apache Digester。

            Here is a small tutorial

            【讨论】:

              猜你喜欢
              • 2014-05-24
              • 2013-09-01
              • 2017-08-14
              • 1970-01-01
              • 1970-01-01
              • 2011-02-18
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多