我正在使用Apache Poi XSSFWorkbooks来操纵 xlsx 文件;我的程序在小excel文件(60 000行)上工作正常。当我开始在一个大文件(700 000行)上测试我的代码时,我遇到了内存问题。我在具有16 GB RAM的计算机上测试我的代码并且它不起作用。
有关此问题的任何帮助吗?我读了SAX解析器,但我不想修改我的代码,而且我发现它不直观易用;它不是简单的 xssf ,它有简单的方法来获取单元格,行..等等
有没有办法保持我的代码不变并解决内存问题?或SAX解析器以外的任何解决方案?感谢任何帮助。谢谢。
答案 0 :(得分:4)
根据经验,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。但是,它经常 ISN'吨!一台温和的笔记本电脑,堆积不错但堆积不大, 从一开始,通常可以读取或写入100的文件 列和100,000行在几秒钟内,包括 是时候启动JVM了。
Apache POI附带了一些程序和一些示例程序 可以用来做一些基本的性能检查。用于测试文件 生成,要使用的类在示例包中, SSPerformanceTest(viewvc)。使用参数运行SSPerformanceTest 写入类型(HSSF,XSSF或SXSSF),行数,数量 列,以及是否应保存文件。如果你不能用它 在3秒内,HSSF和SXSSF中有50,000行和50列,和 XSSF在10秒内(理想情况下,所有3都小于那个!),然后 问题出在您的环境中。
接下来,使用示例程序ToCSV(viewvc)尝试读取文件 使用HSSF或XSSF。相关的是XLSX2CSV(viewvc),它使用SAX 解析.xlsx。对你的问题文件和a运行这个 由SSPerformanceTest生成的相同大小的简单文件。如果是这样的话 慢,那么文件的方式可能存在Apache POI问题 正在处理(POI做出一些可能并非总是如此的假设 对所有文件都正确)。如果这些测试很快,那么任何性能 你的代码中存在问题!
和
Files vs InputStreams 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();