Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/15.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_Memory Management_Streaming_Sax - Fatal编程技术网

用java解析非常大的XML文档(还有更多)

用java解析非常大的XML文档(还有更多),java,xml,memory-management,streaming,sax,Java,Xml,Memory Management,Streaming,Sax,(以下所有内容都将用Java编写) 我必须构建一个应用程序,将潜在的非常大的XML文档作为输入。文档是加密的——不是使用XMLsec,而是使用我的客户机先前存在的加密算法——将分三个阶段进行处理: 首先,将根据上述算法对流进行解密 其次,扩展类(由第三方编写到我提供的API)将读取文件的某些部分。读取的量是不可预测的——特别是不能保证在文件头中,但可能发生在XML中的任何一点 最后,另一个扩展类(相同的交易)将把输入XML细分为1..n个子集文档。这些可能在某些方面与第二个操作处理的文档部分重叠

(以下所有内容都将用Java编写)

我必须构建一个应用程序,将潜在的非常大的XML文档作为输入。文档是加密的——不是使用XMLsec,而是使用我的客户机先前存在的加密算法——将分三个阶段进行处理:

首先,将根据上述算法对流进行解密

其次,扩展类(由第三方编写到我提供的API)将读取文件的某些部分。读取的量是不可预测的——特别是不能保证在文件头中,但可能发生在XML中的任何一点

最后,另一个扩展类(相同的交易)将把输入XML细分为1..n个子集文档。这些可能在某些方面与第二个操作处理的文档部分重叠,即:我相信我需要倒带处理此对象所使用的任何机制

我的问题是:

有没有一种方法可以做到这一点,而不必一次性将整段数据读入内存?显然,我可以将解密实现为一个输入流过滤器,但我不确定是否有可能以我描述的方式解析XML;通过浏览收集第二步信息所需的尽可能多的文档,然后将文档倒带并再次传递以将其拆分为作业,理想情况下,释放文档中传递后不再使用的所有部分。

您可以使用缓冲区大小非常大的,在扩展类工作之前使用
mark()
,然后使用
reset()

但是,如果扩展类所需的部分在文件中的位置非常远,那么这可能会占用大量内存


一个更通用的解决方案是编写自己的
BufferedInputStream
——如果要缓冲的数据超过某个预设阈值,则类似于将数据缓冲到磁盘。

您可能感兴趣的是:

XOM非常独特,因为它是一个 双流/基于树的API。 树中的单个节点可以是 在文档仍处于活动状态时处理 正在建造中。启用XOM程序 运行速度几乎与 底层解析器可以提供数据。你 不需要等待文档完成 在您可以之前,请先完全解析 开始使用它

XOM非常节省内存。如果你 将整个文档读入内存, XOM使用尽可能少的内存。 更重要的是,XOM允许您 在构建文档时对其进行筛选,以便 您不必构建 你不感兴趣的树。对于 例如,可以跳过生成文本 仅表示边界的节点 空白,如果空白是 在您的应用程序中不重要。 您甚至可以处理文档片段 一块一块地扔掉每一块 当你做完它的时候。XOM一直是 用于处理以下文档: 千兆字节大小


这听起来像是StAX()的工作。StAX是一个pull解析器,这意味着它的工作方式或多或少类似于SAX之类的基于事件的解析器,但您可以更好地控制何时停止读取、提取哪些元素

此解决方案的可用性在很大程度上取决于扩展类的实际操作,如果您可以控制它们的实现,等等

主要的一点是,如果文档非常大,您可能希望使用基于事件的解析器,而不是基于树的解析器,因此不会占用大量内存


StAX的实现可以从SUN()或其他一些提供商那里找到。

StAX是正确的方法。我建议查看我将编写
InputStream
的自定义实现,对文件中的字节进行解密,然后使用SAX解析从流中导出的XML

SAXParserFactory.newInstance().newSAXParser().parse(
  new DecryptingInputStream(), 
  new MyHandler()
);
看看图书馆。您正在查找的示例是源发行版的samples目录中的
StreamingExampleExtractor.java
。这展示了一种只构建特定节点、处理它们并丢弃它们的技术,用于对大型xml文档执行流解析。它与sax方法非常相似,但是内置了更多的解析功能,因此可以非常轻松地实现流解析


如果你想在更高的层次上工作,请查看。这提供了一个高级流式xpath API,它只将计算xpath所需的数据量读取到内存中。

这看起来是一种有趣且可能有用的方法,但在文档中没有任何一个地方提供了按照您描述的方式控制文档解析的方法。我相信你可以,但这种能力并没有以一种合理的方式记录下来。只要我能有效地利用它,这看起来很有希望。看起来我必须向API的客户机公开StAX,这不太理想,但至少看起来功能已经具备。你能用一个推荐的实现而不是列表来修改你的帖子吗?我知道这是一个旧的答案/评论,但是有一些lib可以在stax之上增加一些便利性(并隔离一些较低级别的细节),例如StaxMate[。这仍然允许增量解析/编写,但减少了要编写的代码量。