9

几年前,我遇到了使用jXLS和创建大型 Excel 文件的问题POI XSSF。如果我的记忆是正确的,我认为XSSF会在磁盘上创建 1GB+ 的临时文件来创建 10mb 的 excel 文件。所以我停止使用jXLS,而是用来SXSSF创建 excel 文件,但今天我有新的理由使用jXLSor JETT

jXLS和网站似乎都JETT暗示性能要好得多,但POIXSSF网站仍然笼统地说XSSF需要更高的内存占用。我想知道现在这种更高的内存占用是否是合理的 10% 开销,或者它是否仍然像几年前那样的 10,000% 开销。

POI 3.9 修复了疯狂的坏记忆问题XSSF吗?我不应该担心将它与jXLSor一起使用JETT吗?还是有一些需要避免的陷阱?我很小心重用单元格样式。

4

1 回答 1

7

要回答您的问题,是的,在处理大型 XLSX 文件时,POI 总是会使用非常大量的内存,这比 XLSX 文件的大小要大得多。我认为这不会很快改变,并且有很明显的原因:XLSX 基本上是一堆压缩的 XML 文件,并且 XML 被很好地压缩(大约 10 倍)。让这个 XML 不压缩地放在内存中已经使内存消耗增加了十倍,所以如果你添加数据结构的所有开销,你不可能期望内存消耗比 XLSX 文件大小增加 10%。

现在,好消息是,正如评论中提到的,Apache POI 引入了SXSSF,用于在电子表格中流式传输大量数据,具有非常好的性能和低内存使用率。以这种方式生成的 XLSX 文件仍然在硬盘上流式传输,最终可能会占用相当多的空间,但至少在写入数十万行时不会冒 OOME 的风险。

您的问题是您将无法让 JETT 直接使用 SXSSF,因为它需要将整个文档加载到内存中以执行模板填充。JETT作者在这里快速讨论了这个话题。

我遇到了同样的问题,最后做了两步 XLSX 创建:

  1. 用于生成标题和格式的标准 JETT XLSX 模板。第一张表的最后一行包含带有 $$tokens$$ 的单元格,每个单元格一个。我不使用 JETT 插入大量行。

  2. JETT 完成工作后,我重新打开工作簿,阅读并删除第一个电子表格最后一行的 $$tokens$$,然后开始使用 SXSSF 逐行流式传输数据。

当然,这种方法有一些限制: - 在行插入期间,您不能在任何流式行上使用 JETT(但您之前可以,例如动态选择 $$tokens$$ 的顺序) - 单元格格式不会除非您使用 POI API 自己处理,否则不会被复制。我个人更喜欢在我的 XLSX 文件中格式化整个列,它将应用于流数据。

如果您想使用通过 SXSSF 插入的数据显示图表,这也适用:您可以使用函数 OFFSET 和 COUNTA 定义一个命名范围,然后创建一个数据透视表和数据透视图,当在 Excel 中打开 XLSX 时将刷新该数据透视表和数据透视图。

于 2015-05-12T09:33:15.087 回答