根据经验,SAX 确实对内存性能有很大帮助。从 4GB+ 增加到 300MB 左右。
一些有用的链接和其他提示:
来自https://poi.apache.org/spreadsheet/limitations.html
文件大小/内存使用情况
Excel 文件格式存在一些固有限制。这些都是
在类 SpreadsheetVersion 中定义。只要你有足够的
主内存,您应该能够处理达到这些限制的文件。
对于使用默认 POI 类的大文件,您可能需要一个
非常大的内存量。
如果需要,有一些方法可以克服主存限制:对于
写非常大的文件,有 SXSSFWorkbook 允许做一个
将数据流式写入文件(对什么有一定的限制)
您可以这样做,因为只有部分文件保存在内存中)。用于阅读
非常大的文件,看看示例 XLSX2CSV,它显示了如何
您可以以流方式读取文件(同样有一些限制
你可以从文件中读出哪些信息,但有一些方法
如有必要,最多获得它)。
还有
https://poi.apache.org/faq.html#faq-N10165
- 我认为 POI 占用了太多内存!我能做些什么?这个出现了很多,但通常原因不是你可能的
初步认为。所以,首先要检查的是——来源是什么
的问题?你的文件?你的代码?你的环境?还是 Apache POI?
(如果你在这里,你可能会认为它是 Apache POI。然而,它经常
不是!一台中等大小的笔记本电脑,堆大小适中但不过大,
从一开始,可以正常读取或写入 100 个文件
在几秒钟内完成列和 100,000 行,包括
是时候启动 JVM)。
Apache POI 附带了一些程序和一些示例程序,它们
可以用来做一些基本的性能检查。用于测试文件
生成,要使用的类在示例包中,
SSPerformanceTest (viewvc)。使用参数运行 SSPerformanceTest
书写类型(HSSF、XSSF 或 SXSSF)、行数、行数
列,以及是否应保存文件。如果你不能运行它
HSSF 和 SXSSF 在 3 秒内完成 50,000 行和 50 列,以及
XSSF 不到 10 秒(理想情况下,所有 3 秒不到!),然后
问题在于您的环境。
接下来,使用示例程序 ToCSV (viewvc) 尝试读取文件
与 HSSF 或 XSSF 一起使用。相关的是使用 SAX 的 XLSX2CSV (viewvc)
解析.xlsx。对您的问题文件和一个
由相同大小的 SSPerformanceTest 生成的简单。如果这是
慢,那么文件的方式可能存在 Apache POI 问题
正在处理(POI 做出一些可能并不总是
正确的所有文件)。如果这些测试很快,那么任何性能
你的代码有问题!
和
文件与输入流http://poi.apache.org/spreadsheet/quick-guide.html#FileInputStream
When opening a workbook, either a .xls HSSFWorkbook, or a .xlsx XSSFWorkbook, the Workbook can be loaded from either a File or an InputStream. Using a File object allows for lower memory consumption, while an InputStream requires more memory as it has to buffer the whole file.
If using WorkbookFactory, it's very easy to use one or the other:
// Use a file
Workbook wb = WorkbookFactory.create(new File("MyExcel.xls"));
// Use an InputStream, needs more memory
Workbook wb = WorkbookFactory.create(new FileInputStream("MyExcel.xlsx"));
如果直接使用 HSSFWorkbook 或 XSSFWorkbook,一般应该
通过 NPOIFSFileSystem 或 OPCPackage,可以完全控制
生命周期(包括完成后关闭文件):
// HSSFWorkbook, File
NPOIFSFileSystem fs = new NPOIFSFileSystem(new File("file.xls"));
HSSFWorkbook wb = new HSSFWorkbook(fs.getRoot(), true);
....
fs.close();
// HSSFWorkbook, InputStream, needs more memory
NPOIFSFileSystem fs = new NPOIFSFileSystem(myInputStream);
HSSFWorkbook wb = new HSSFWorkbook(fs.getRoot(), true);
// XSSFWorkbook, File
OPCPackage pkg = OPCPackage.open(new File("file.xlsx"));
XSSFWorkbook wb = new XSSFWorkbook(pkg);
....
pkg.close();
// XSSFWorkbook, InputStream, needs more memory
OPCPackage pkg = OPCPackage.open(myInputStream);
XSSFWorkbook wb = new XSSFWorkbook(pkg);
....
pkg.close();