在不使用 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
文件格式,又增加了一层。这是 SS
和 XSSF
级别,提供 apache poi
的高级别 类。因此,现在有额外的 java
工作簿、工作表、行、单元格、绘图、表格、数据透视表、图表等对象,除了低级别 ooxml-schemas
类在记忆中。
所以...涉及大 *.xlsx
文件时内存已满。 ;-)
解决方案?
为了尽可能便于记忆,请解压缩 *.xlsx
ZIP 存档并直接使用其中的 XML。当然这是非常费力的,特别是对于创建新内容以及考虑到关系。我在此处的回答中为此展示了简单的示例。例如: and How to set cell background color in excel using java + poi.
或者为 apache poi
编写扩展程序,它使用临时文件而不是将所有文件保存在内存中。当然这也很费力并且对于不提供使用临时文件的系统有缺点。
我正在尝试更新现有的 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
文件格式,又增加了一层。这是 SS
和 XSSF
级别,提供 apache poi
的高级别 类。因此,现在有额外的 java
工作簿、工作表、行、单元格、绘图、表格、数据透视表、图表等对象,除了低级别 ooxml-schemas
类在记忆中。
所以...涉及大 *.xlsx
文件时内存已满。 ;-)
解决方案?
为了尽可能便于记忆,请解压缩 *.xlsx
ZIP 存档并直接使用其中的 XML。当然这是非常费力的,特别是对于创建新内容以及考虑到关系。我在此处的回答中为此展示了简单的示例。例如:
或者为 apache poi
编写扩展程序,它使用临时文件而不是将所有文件保存在内存中。当然这也很费力并且对于不提供使用临时文件的系统有缺点。