使用Apache POI打开12M未损坏xlsm文件无响应无报错如何解决?
Apache POI加载XLSM文件无响应解决方案
核心原因:XSSFWorkbook属于全量内存加载模式,会把文件内所有数据、公式、宏、样式、隐藏内容全部加载到堆内存,12MB的XLSM源文件加载后内存通常会膨胀10~100倍,若文件包含大量数组公式、循环引用、宏代码,就会出现无报错卡死、内存持续上涨的情况。
修复步骤
- 调整JVM启动堆内存参数,先保证内存足够:
给Java进程添加启动参数:-Xms4g -Xmx8g,若文件内容特别复杂可继续上调Xmx上限。 - 替换文件加载方式,不要使用
FileInputStream:
POI官方明确说明,传入File对象加载Excel的内存占用比传入InputStream低50%以上,避免全量文件缓存到内存。 - 按需禁用不必要的加载项:
若不需要读取/修改宏,加载前设置XSSFWorkbook.setMacrosEnabled(false);若不需要公式计算,加载后设置workbook.setForceFormulaRecalculation(false),避免POI自动计算公式导致卡死。 - 大文件场景使用流式读取:
若仅需要读取单元格内容,不需要修改文件、读取样式/宏,直接使用你注释中的StreamingReader流式加载方案,内存占用稳定在几十MB,不会出现全量加载的卡顿问题。 - 升级POI版本:
若当前使用的POI版本低于4.1.2,建议升级到最新稳定版,老版本对XLSM格式的宏处理、大文件加载存在大量已知bug,会导致无响应问题。
修正后的参考代码
// 需要编辑文件、读取宏/样式的加载方案 public XSSFWorkbook openExcelFile(String excelFilePath) throws IOException { // 不需要读取宏时开启该配置 XSSFWorkbook.setMacrosEnabled(false); // 直接传File对象,不要用FileInputStream XSSFWorkbook workbook = (XSSFWorkbook) WorkbookFactory.create(new File(excelFilePath)); // 不需要自动计算公式时开启该配置 workbook.setForceFormulaRecalculation(false); return workbook; } // 仅读取单元格数据的流式加载方案 public void readExcelByStreaming(String excelFilePath) throws IOException { try (StreamingReader reader = StreamingReader.builder() .rowCacheSize(100) .bufferSize(4096) .open(new File(excelFilePath))) { for (Sheet sheet : reader) { for (Row row : sheet) { for (Cell cell : row) { // 按需处理单元格内容 System.out.println(cell.getStringCellValue()); } } } } }
内容的提问来源于stack exchange,提问作者Alessandro Tediosi
相关产品推荐
相关产品推荐

