在Java中计算xml节点最有效的方法是什么

在Java中计算xml节点最有效的方法是什么,java,xml,Java,Xml,我有一个高达1-2gb的巨大XML文件,显然我不能一次解析整个文件,我必须将其拆分为多个部分,然后解析这些部分并对其执行任何操作 如何计算某个节点的数量?因此,我可以跟踪分割文件需要多少部分。有没有更好的办法?我愿意接受所有建议谢谢 问题更新: 我确实使用了STAX,也许我使用它的逻辑是错误的,我正在解析文件,然后对于每个节点,我得到节点值并将其存储在string builder中。然后在另一种方法中,我通过stringbuilder编辑输出。然后我将输出写入文件。我最多只能做10000个这样的

我有一个高达1-2gb的巨大XML文件,显然我不能一次解析整个文件,我必须将其拆分为多个部分,然后解析这些部分并对其执行任何操作

如何计算某个节点的数量?因此,我可以跟踪分割文件需要多少部分。有没有更好的办法?我愿意接受所有建议谢谢

问题更新:

我确实使用了STAX,也许我使用它的逻辑是错误的,我正在解析文件,然后对于每个节点,我得到节点值并将其存储在string builder中。然后在另一种方法中,我通过stringbuilder编辑输出。然后我将输出写入文件。我最多只能做10000个这样的对象

以下是我得到的一个例外:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
        at com.sun.org.apache.xerces.internal.util.NamespaceSupport.<init>(Unkno
wn Source)
        at com.sun.xml.internal.stream.events.XMLEventAllocatorImpl.setNamespace
Context(Unknown Source)
        at com.sun.xml.internal.stream.events.XMLEventAllocatorImpl.getXMLEvent(
Unknown Source)
        at com.sun.xml.internal.stream.events.XMLEventAllocatorImpl.allocate(Unk
nown Source)
        at com.sun.xml.internal.stream.XMLEventReaderImpl.nextEvent(Unknown Sour
ce)
        at com.sun.org.apache.xalan.internal.xsltc.trax.StAXEvent2SAX.bridge(Unk
nown Source)
        at com.sun.org.apache.xalan.internal.xsltc.trax.StAXEvent2SAX.parse(Unkn
own Source)
        at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transfor
mIdentity(Unknown Source)
        at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transfor
m(Unknown Source)
        at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transfor
m(Unknown Source)
线程“main”java.lang.OutOfMemoryError中的异常:java堆空间 请访问com.sun.org.apache.xerces.internal.util.NamespaceSupport (来源) 位于com.sun.xml.internal.stream.events.XMLEventAllocatorImpl.setNamespace 上下文(未知源) 位于com.sun.xml.internal.stream.events.XMLEventAllocatorImpl.getXMLEvent( (未知来源) 位于com.sun.xml.internal.stream.events.XMLEventAllocatorImpl.allocate(Unk 未知来源) 位于com.sun.xml.internal.stream.XMLEventReaderImpl.nextEvent(未知) (行政长官) 位于com.sun.org.apache.xalan.internal.xsltc.trax.statxevent2sax.bridge(Unk 未知来源) 在com.sun.org.apache.xalan.internal.xsltc.trax.statxevent2sax.parse(Unkn (自有来源) 位于com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transfor 中间实体(未知源) 位于com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transfor m(未知来源) 位于com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transfor m(未知来源) 实际上,我认为我的整个方法是错误的,我实际上是在尝试将xml文件转换为CSV示例。到目前为止,我是这样做的:

  • 读取/解析xml文件
  • 对于每个元素节点,获取文本节点值
  • 打开流将其写入文件(temp),对于n个节点,然后刷新并关闭流
  • 然后打开另一个从temp读取的流,使用commons strip utils和其他一些东西来创建正确的csv输出,然后将其写入csv文件

您最好使用基于事件的解析器,如SAX或STAX API。他们不会一次解析整个过程,他们一次只处理一个节点,让你的应用程序处理它。它们适用于任意大的文档

SAX是较旧的API,在推送模型上工作,STAX是较新的,是一个拉式解析器,因此更易于使用,但对于您的需求,任何一种都可以


请参阅以开始使用STAX解析。

我认为您希望避免创建DOM,所以or应该是一个不错的选择


使用SAX,只需实现一个simlpe内容处理程序,如果找到一个感兴趣的元素,它只需增加一个计数器。

您可以使用类似的流式解析器。这将不需要您一次读取内存中的整个文件。

您不必拆分文件:它是流式的,因此它只保存内存中的当前位。编写一个只进行计数的ContentHandler非常容易。而且速度非常快(以我的经验,几乎和读取文件一样快)。

我认为拆分文件不是一种好方法。您最好将xml文件作为流处理,并使用SAXAPI(而不是DOM API)

更好的是,您应该使用XQuery来处理您的请求

Saxon是一个很好的Java/.Net实现(使用sax),速度惊人,即使在大文件上也是如此。版本他在MPL开源许可下

下面是一个小例子:

java -cp saxon9he.jar net.sf.saxon.Query -qs:"count(doc('/path/to/your/doc/doc.xml')//YouTagToCount)"
我确实使用了STAX,也许我使用它的逻辑是错误的,我正在解析文件,然后对于每个节点,我得到节点值并将其存储在string builder中。然后在另一种方法中,我通过stringbuilder编辑输出。然后我将输出写入文件。我最多只能做10000个这样的对象

根据这个描述,我会说是的,你使用它的逻辑是错误的。你的记忆太多了

与解析整个文件、将所有节点值存储到某个文件中然后处理结果不同,您应该在点击每个节点时对其进行处理,并在解析时输出


有了更多关于您实际要完成的任务以及输入XML和输出XML的详细信息,我们可能有助于简化流程。

使用扩展vtd XML,您可以高效地在内存中加载文档,因为它支持内存映射。与DOM相比,内存使用量不会在数量级上爆炸。您将能够非常轻松地使用xpath计算节点数。

+1提到StaX(pull)比SAX更易于使用。您所说的“不超过10000个这样的对象”是什么意思?您捕获了什么错误或异常?STAX API不使用大量内存,但是如果您自己的程序在STAX执行迭代时存储了大量数据,那么这不是STAX的错误。您需要整理自己的内存管理,而不是选择不同的XML API。为什么要将值存储在stringbuilder中,为什么不能处理独立节点值?