在Java Apache POI中更新现有Excel文件而不使用InputStream

在Java Apache POI中更新现有Excel文件而不使用InputStream,java,excel,apache-poi,xssf,Java,Excel,Apache Poi,Xssf,我正在尝试更新现有的Excel文件(xlsx) 构造函数,如xssf工作簿(java.io.File文件)和xssf工作簿(OPCPackage pkg)以只读模式打开文件,不允许修改。因此,我必须使用xssf工作簿(java.io.InputStream is),内存占用(JVM内存和java堆)太高。我不能使用VM参数来设置最大内存大小,因为我必须考虑并行运行的其他程序的内存需求 使用SXSSFWorkbook是另一种解决方案,但它本质上是XSSFWorkbook的包装器。与XSSFWork

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

构造函数,如
xssf工作簿(java.io.File文件)
xssf工作簿(OPCPackage pkg)
以只读模式打开文件,不允许修改。因此,我必须使用
xssf工作簿(java.io.InputStream is)
,内存占用(JVM内存和java堆)太高。我不能使用VM参数来设置最大内存大小,因为我必须考虑并行运行的其他程序的内存需求

使用
SXSSFWorkbook
是另一种解决方案,但它本质上是
XSSFWorkbook
的包装器。与
XSSFWorkbook
相同的问题仍然存在


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

你的问题不清楚。实际上,这不是“如何在不使用输入流的情况下打开
xssfoolk
”,而是“如何减少
xssfoolk
?”的内存占用”。这个问题的答案是:它不能被简化,比如
apachepoi
现在已经被编程了。否则
apache-poi
开发人员一定会像编程
apache-poi
那样愚蠢,尤其是为了浪费内存。他们没有

但是使用了太多的抽象级别

所有这些都基于XML。但是编程库的用户不想麻烦使用XML,至少不想麻烦使用这种XML,这种XML在一个ZIP存档中被分割成多个文件,这些文件使用特殊关系XML文件链接在一起。因此,在XML之上还有
ooxml模式
,一个库,它将单个文件的XML转换成可用的
java
对象。还有
org.apache.poi.openxml4j.opc.*
来管理这些关系

为了从中获益,所有可用的
java
对象(工作簿、工作表、行、单元格、图形、表格、透视表、图表等)以及它们之间的关系必须在内存中才能使用。或者,在将它们从
*.xlsx
ZIP存档中取出后,必须使用临时文件临时存储它们。在我看来,直接在ZIP文件系统中工作不是一个选项,因为这种类型的文件系统中的更改行为

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

另外,为了尽可能与二进制
BIFF
*.xls
文件格式兼容,添加了另一个级别。这是
SS
XSSF
级别,它提供了
apachepoi
的高级类。正因为如此,现在有了用于工作簿、工作表、行、单元格、图形、表格、数据透视表、图表等的附加
java
对象。。除了内存中的低级
ooxml模式
类之外

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

解决方案

为了尽可能对内存友好,请解压缩
*.xlsx
ZIP归档文件并直接使用其中的XML。当然,这是非常费劲的,尤其是在创造新的内容和考虑到这些关系时。我在这里的回答中给出了一些简单的例子。例如:和

或者为
apachepoi
编程一个扩展,它使用临时文件而不是将所有文件都保存在内存中。当然,这也很费劲,对于不提供使用临时文件的系统也有缺点。

我使用新的SXSSFWorkbook(-1)和SXSSFSheet.flushRows()获得了很好的效果(内存使用率较低),但这是为了创建新文件,而不是更新文件。我想你应该试试SXSSFWorkbook