巨大的XML文件到文本文件

use*_*035 9 java xml

我有一个巨大的XML文件(15 GB).我想将XML文件中的"text"标记转换为单个页面.

示例XML文件:

<root>
    <page>
        <id> 1 </id>
        <text>
        .... 1000 to 50000 lines of text
        </text>
    </page>
    ... Like wise 2 Million `page` tags
</root>
Run Code Online (Sandbox Code Playgroud)

我最初使用DOM解析器,但它会抛出JAVA OUT OF MEMORY(有效).现在,我使用STAX编写了JAVA代码.它运作良好,但性能非常慢.

这是我写的代码:

 XMLEventReader xMLEventReader = XMLInputFactory.newInstance().createXMLEventReader(new FileInputStream(filePath));
    while(xMLEventReader.hasNext()){
      xmlEvent = xMLEventReader.nextEvent();

    switch(xmlEvent.getEventType()){
    case XMLStreamConstants.START_ELEMENT:
    if( element == "text")
      isText    = true;
    break;
    case XMLStreamConstants.CHARACTERS:
      chars = (Characters) xmlEvent;
      if(! (chars.isWhiteSpace() || chars.isIgnorableWhiteSpace()))
               if(isText)
              pageContent += chars.getData() + '\n';
      break;
    case XMLStreamConstants.END_ELEMENT:
      String elementEnd = (((EndElement) xmlEvent).getName()).getLocalPart();
      if( elementEnd == "text" )
      {
          createFile(id, pageContent);
          pageContent = "";
          isText = false;
      }
      break;
    }
}
Run Code Online (Sandbox Code Playgroud)

这段代码运行良好.(忽略任何小错误).根据我的理解,XMLStreamConstants.CHARACTERS迭代文本标记的每一行.如果TEXT标记中有10000行,则XMLStreamConstants.CHARACTERS将迭代下一行10000行.有没有更好的方法来改善性能..?

Jas*_*n C 1

什么是pageContent?它似乎是一个String. 立即进行的一个简单的优化是使用 aStringBuilder来代替;它可以附加字符串,而不必像Strings+=那样制作字符串的全新副本(如果您一开始就知道长度,您也可以使用初始保留容量来构造它,以减少内存重新分配和副本)。

连接Strings 是一个缓慢的操作,因为字符串在 Java 中是不可变的;每次调用a += b它时都必须分配一个新字符串,复制a到其中,然后复制b到它的末尾;使每个串联都为 O(n)。两个字符串的总长度。附加单个字符也是如此。StringBuilder另一方面,具有与ArrayList附加时相同的性能特征。所以你有:

pageContent += chars.getData() + '\n';
Run Code Online (Sandbox Code Playgroud)

相反,更改pageContent为 aStringBuilder并执行以下操作:

pageContent.append(chars.getData()).append('\n');
Run Code Online (Sandbox Code Playgroud)

此外,如果您猜测这些字符串之一的长度上限,则可以将其传递给StringBuilder构造函数以分配初始容量,并减少必须完成内存重新分配和完整复制的机会。

顺便说一句,另一种选择是完全跳过StringBuilder并将数据直接写入输出文件(假设您没有首先以某种方式处理数据)。如果您这样做,并且性能受到 I/O 限制,那么选择不同物理磁盘上的输出文件会有所帮助。