【问题标题】:Manipulate big XML file in Java Spring在 Java Spring 中操作大 XML 文件
【发布时间】: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 树加载到内存中。

标签: java spring


【解决方案1】:

您可以在将字节转换为字符串后从内存中删除传入的字节:

byte[] bytes = bytesFromURL;
String xml = new String(bytes);
{...manipulate xml}
bytes = null;
System.gc();
bytes = xml.getBytes();

【讨论】:

  • 直接调用垃圾收集器真的很糟糕。
  • 在这种情况下,它可能有用stackoverflow.com/a/4785113/7739083
  • 不,在大多数情况下这是一种黑客行为,在这种情况下确实有更好的解决方案。 (SAX、Stax)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-11-07
  • 1970-01-01
  • 1970-01-01
  • 2013-01-09
  • 1970-01-01
  • 2015-08-12
  • 1970-01-01
相关资源
最近更新 更多