在不使用 InputStream 的情况下更新 Java Apache POI 中的现有 Excel 文件

Updating existing Excel file in Java Apache POI without using InputStream

我正在尝试更新现有的 Excel 文件 (xlsx)。

XSSFWorkbook(java.io.File file)XSSFWorkbook(OPCPackage pkg)这样的构造函数以只读模式打开文件并且不允许修改。所以我必须使用 XSSFWorkbook(java.io.InputStream is) 并且内存占用(JVM 内存和 Java 堆)太高了。我不能使用 VM args 来设置最大内存大小,因为我必须并行地尊重其他程序 运行 的内存要求。

使用 SXSSFWorkbook 是另一种解决方案,但它本质上是对 XSSFWorkbook 的包装。与 XSSFWorkbook.

相同的问题仍然存在

我去了 SO 的其他帖子,但找不到任何相关答案。有人可以帮我吗?我可以存储临时文件。

你的问题不清楚。实际上它不是 "How to open XSSFWorkbook without using InputStream?" 而是 "How to reduce the memory footprint of XSSFWorkbook? "。而这道题的答案是:不能减,比如现在编程apache poi。否则 apache poi 开发人员一定很愚蠢,他们编写 apache poi 特别是为了浪费内存。他们还没有。

但是使用了太多的抽象层次。

全部基于XML。但是编程库的用户不想打扰 XML,至少不想打扰那种 XML,它被分成 ZIP 存档中的多个文件,这些文件使用特殊关系 XML 链接在一起文件。所以在 XML 之上有一个库 ooxml-schemas,它将单个文件的 XML 转化为可用的 java 对象。还有 org.apache.poi.openxml4j.opc.* 来管理关系。

为了充分利用此功能,所有可用的 java 对象(工作簿、工作表、行、单元格、绘图、表格、数据透视表、图表...)以及这些对象的关系 必须在内存中才能使用。或者在将它们从 *.xlsx ZIP 存档中取出后,必须使用临时文件来临时存储它们。在我看来,直接在 ZIP 文件系统中工作不是一种选择,因为这种类型的文件系统的行为会发生变化。

但是apache poi不提供使用临时文件。只有 SXSSF 将临时文件用于工作表,但仅用于写入新的 *.xlsx 文件,而不用于读取和更新此类文件。

另外,为了尽可能兼容二进制BIFF *.xls文件格式,又增加了一层。这是 SSXSSF 级别,提供 apache poi 的高级别 类。因此,现在有额外的 java 工作簿、工作表、行、单元格、绘图、表格、数据透视表、图表等对象,除了低级别 ooxml-schemas 类在记忆中。

所以...涉及大 *.xlsx 文件时内存已满。 ;-)

解决方案?

为了尽可能便于记忆,请解压缩 *.xlsx ZIP 存档并直接使用其中的 XML。当然这是非常费力的,特别是对于创建新内容以及考虑到关系。我在此处的回答中为此展示了简单的示例。例如: and How to set cell background color in excel using java + poi.

或者为 apache poi 编写扩展程序,它使用临时文件而不是将所有文件保存在内存中。当然这也很费力并且对于不提供使用临时文件的系统有缺点。