Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 巨大的XML文件到文本文件_Java_Xml - Fatal编程技术网

Java 巨大的XML文件到文本文件

Java 巨大的XML文件到文本文件,java,xml,Java,Xml,我有一个巨大的XML文件(15GB)。我想将XML文件中的“文本”标记转换为单个页面 示例XML文件: <root> <page> <id> 1 </id> <text> .... 1000 to 50000 lines of text </text> </page> ... Like wise 2 Million `page

我有一个巨大的XML文件(15GB)。我想将XML文件中的“文本”标记转换为单个页面

示例XML文件:

<root>
    <page>
        <id> 1 </id>
        <text>
        .... 1000 to 50000 lines of text
        </text>
    </page>
    ... Like wise 2 Million `page` tags
</root>
此代码运行良好。(忽略任何小错误)。根据我的理解,XMLStreamConstants.CHARACTERS会对文本标记的每一行进行迭代。如果文本标记中有10000行,则XMLStreamConstants.CHARACTERS将在接下来的10000行中迭代。有没有更好的方法来提高性能?

您的代码看起来很标准。 但是,您能否尝试将FileInputStream包装到BufferedInputStream中,并告诉我们这是否有帮助? BufferedInputstream为您节省了对操作系统的一些本机调用,因此有机会获得更好的性能。
您必须调整缓冲区大小以获得最佳性能。根据JVM内存分配设置一些大小。

尝试使用SAX解析器进行解析,因为DOM将尝试解析整个内容并将其放入内存中。因此,您会遇到内存异常。SAX解析器不会一次解析整个内容。

我可以看到一些可能的解决方案,它们可能会帮助您:

  • 使用
    BufferedInputStream
    而不是简单的
    FileInputStream
    来减少磁盘操作的数量
  • 考虑使用
    StringBuilder
    来创建页面内容,而不是字符串链接
  • 增加Java堆(
    -Xmx
    选项),以防2GB示例内存受限
  • 在这种情况下,连接一个代码探查器(例如)是非常有趣的,因为这样您就可以确切地看到代码中哪些方法调用速度慢。然后,您可以适当地关注优化

  • 文件输入流周围使用
    BufferedInputStream
  • 不要连接数据。这完全是浪费时间和空间,可能会浪费很多空间。你一拿到就把它写下来。在
    FileWriter
    周围使用
    BufferedWriter

  • 如果解析XML文件是主要问题,请考虑使用,即扩展版本,因为它支持文件高达256GB。
    由于它基于非抽取式文档解析,因此内存效率很高,使用XPath查询/提取文本也非常快。您可以从中阅读有关此方法和VTD-XML的更多详细信息。

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

    串接
    String
    s是一个缓慢的操作,因为字符串在Java中是不可变的;每次调用
    a+=b
    时,它必须分配一个新字符串,将
    a
    复制到该字符串中,然后将
    b
    复制到该字符串的末尾;使每个连接O(n)wrt。两个字符串的总长度。附加单个字符也是如此<另一方面,代码>StringBuilder在追加时具有与
    阵列列表
    相同的性能特征。因此,你有:

    pageContent += chars.getData() + '\n';
    
    改为将
    pageContent
    更改为
    StringBuilder
    ,并执行以下操作:

    pageContent.append(chars.getData()).append('\n');
    
    此外,如果您对其中一个字符串的长度上限有一个猜测,则可以将其传递给
    StringBuilder
    构造函数,以分配初始容量,并减少必须进行内存重新分配和完整复制的机会


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

    出于好奇,您当前加载和解析该文件需要多长时间?我已经解析了2GB文件。花了35分钟..什么是
    pageContent
    ?它是一个
    字符串
    ?如果是这样,一个简单的优化方法就是使用
    StringBuilder
    ;它可以附加字符串,而不必像
    String
    s
    +=
    那样制作字符串的全新副本(如果您知道开始的长度,还可以使用初始保留容量来构造它,以减少内存重新分配和副本).恐怕你要花很长时间才能浏览2GB的文件。。。。我对StAX不太熟悉,但在SAX中,字符事件不是每行而是每解析缓冲区中断,可能是多行或一行的一部分,这取决于行的长度以及文本内容启动时您恰好在解析器的输入缓冲区中的位置。为什么不使用可用库来提取内容呢。WikiXMLJ是一个非常好的库,因为他将其替换为一个STAX解析器,该解析器的性能将与SAX解析器一样好。从某种意义上说,它为您节省了大量的系统调用,实际上,默认的缓冲区大小8192对于几乎所有情况都是完全足够的。
    pageContent.append(chars.getData()).append('\n');