【发布时间】:2018-09-05 14:09:50
【问题描述】:
我有一个 Java 程序(战争)在处理一个大的 XML 文件时内存不足。 该程序是一个 REST API,它通过 REST 控制器返回处理后的 XML。
首先,程序从远程 URL 获取 XML 文件。
然后它替换id 属性的值。
最后,它通过 API 控制器将新的 XML 返回给调用者。
我从远程 URL 得到的是带有 XML 数据的 byte[] 正文。
然后,我将其转换为字符串。
接下来,我对整个字符串进行正则表达式搜索替换。
然后我将它转换回byte[]。
我猜 XML 现在在内存中 3 次(传入字节、字符串和传出字节)。
我正在寻找改进方法。
顺便说一句,我在文件系统上没有本地副本。
【问题讨论】:
-
不要将整个数据读入内存,使用流。不要使用正则表达式来处理 XML。考虑切换到 SAX 或 StAX 等流方法。
-
@lexicore 听起来不错。但是,这也适用于 I/O 控制器吗?
-
我不确定,但我认为应该。只要您可以从流(输入文件)读取并写入响应流,这应该可以工作。
-
我这样做的方式:1)不要将远程文件作为字节[]获取,将其作为流获取(HTTP连接是流)。 2)不要将其转换为字符串,在其上实例化 Stax 或 SAX 解析器。 3) 即时修改 id 属性,4) 将结果写入 HttpServletResponse 的输出端,也不要写入 byte[] 或 String。一个完全流式传输的实现应该只需要几 kb 的堆(和/或比最大的 XML 事件多几 kb)。它需要做更多的工作,但它更快、更准确(XML 方面)和更轻量级。
-
@pdem :Java 中没有非商业流式 XSLT 提供程序。据我所知,只有 Saxon EE 这样做。 (一般来说,XSLT 不是一个可流式处理的过程,只是它的一个子集 - 但在这种情况下,它是可行的)。请参阅stackoverflow.com/questions/460895/… 标准 XSLT 以一种或另一种方式将 XML 树加载到内存中。