POI XSSF是否还有疯狂的坏内存问题?

Bob*_*ule 7 java apache-poi xssf jxls jett

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

无论jXLSJETT网站似乎暗示,业绩要好得多,但POIXSSF网站仍然表示一般的XSSF要求更高的内存占用.我想知道这些更高的内存占用量是否像现在合理的10%开销,或者它仍然像几年前的10,000%开销一样.

POI 3.9修复了疯狂的坏内存问题XSSF吗?我应该不用担心使用它jXLSJETT?还是有某些难以避免的陷阱?重用细胞样式我很小心.

Eti*_*e C 7

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

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

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

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

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

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

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

如果要使用SXSSF插入的数据显示图表,也可以使用此选项:您可以使用OFFSET和COUNTA函数定义命名范围,然后创建一个数据透视表和数据透视表,在Excel中打开XLSX时将对其进行刷新.

  • 我认为真正的问题是 POI 使用了糟糕的内部数据结构设计——我认为一般来说,xml 文件比 zip 文件大 12 倍。在报告生成过程中,POI 使用的临时文件比生成的 xlsx 大 1000 倍,因此绝对不仅仅是压缩导致了问题。 (2认同)