使用Apache POI读取大体积XLSX文件遇异常,寻求解决方法
大XLSX文件读取问题的解决方案
1. 改用SXSSF流式处理(优先推荐)
POI的SXSSF是专门为大Excel文件设计的,它会将超出内存阈值的行写入临时磁盘文件,只保留指定数量的行在内存中,大幅降低内存占用。
替换原有的XSSFWorkbook初始化代码:
FileInputStream fis = new FileInputStream(file); // 设置内存中保留1000行,超出部分写入临时文件 SXSSFWorkbook newWorkbook = new SXSSFWorkbook(1000); // 读取工作表数据 SXSSFSheet sheet = newWorkbook.getSheetAt(0); // 遍历行处理数据 for (Row row : sheet) { // 你的单元格处理逻辑 } // 使用完毕后清理临时文件 newWorkbook.dispose(); fis.close();
2. 调整JVM堆内存上限
虽然你在eclipse.ini设置了2G堆,但实际运行程序时可能没生效。需要在运行配置里单独设置VM参数:
- 打开Run > Run Configurations
- 找到你的Java应用,切换到Arguments标签
- 在VM arguments里添加:
-Xms512m -Xmx4096m(根据机器内存调整,比如设为4G)
3. 使用SAX模式的XSSFReader解析(极致低内存)
如果SXSSF仍不够,可使用基于SAX的事件驱动解析,完全不加载整个文档到内存,只在遇到XML节点时处理数据:
OPCPackage pkg = OPCPackage.open(file); XSSFReader reader = new XSSFReader(pkg); // 先读取共享字符串表(处理单元格文本内容) SharedStringsTable sst = reader.getSharedStringsTable(); // 获取所有工作表的输入流 Iterator<InputStream> sheetIter = reader.getSheetsData(); while (sheetIter.hasNext()) { InputStream sheetStream = sheetIter.next(); // 自定义SAX处理器处理工作表内容 XMLReader xmlReader = XMLReaderFactory.createXMLReader(); xmlReader.setContentHandler(new XSSFSheetHandler(sst)); xmlReader.parse(new InputSource(sheetStream)); sheetStream.close(); } pkg.close();
其中XSSFSheetHandler需要你继承DefaultHandler,重写startElement、endElement等方法,来处理行和单元格的解析事件。
4. 检查并优化源Excel文件
如果文件存在单个超大单元格(比如包含数万字的文本),会触发POI的记录长度限制。可以先打开Excel文件,检查是否有异常大的单元格,拆分或清理后再读取。
内容的提问来源于stack exchange,提问作者poojay
相关产品推荐
相关产品推荐

