使用Apache POI写入.xlsx文件极慢问题求助:仅写入2个单元格耗时超35秒
嘿,你的Excel写入性能问题我找到了!
我仔细看了你的代码和问题描述,性能瓶颈完全来自于不必要地用SXSSFWorkbook包装已加载的XSSFWorkbook,再加上资源管理的小问题,这才导致改2个单元格要花35秒以上。下面给你拆解问题和修复方案:
核心问题在哪?
- SXSSFWorkbook用错场景了:SXSSF是专门用来处理超大Excel文件(比如几万几十万行数据)的流式API,它靠把数据分批写到临时文件来节省内存。但你只是修改了2个单元格啊!把已经加载到内存里的XSSFWorkbook转成SXSSF,相当于强制把整个Excel重新序列化一遍,还多了临时文件的IO操作,这可不慢才怪。
- 资源关闭顺序不合理:你先关闭了
fis再执行文件写入,虽然这里没触发严重错误,但正确的顺序应该是先完成写入操作,再依次关闭所有资源。 - 冗余代码拖慢速度:
SXSSFSheet sheetSXSS= book.getSheetAt(0);这行代码获取了Sheet对象后没有任何后续操作,纯粹是多余的性能消耗。
修复后的写入方法(直接快几十倍)
把那些多余的SXSSF代码删掉,直接用原XSSFWorkbook写入即可,同时调整资源关闭顺序:
public static void writeAndCloseALLStream() throws IOException { try { // 直接用已经加载好的XSSFWorkbook写入,这才是修改少量单元格的正确方式 workbook.write(fos); } finally { // 按正确顺序关闭资源:先关工作簿,再关流 workbook.close(); if (fis != null) { fis.close(); } fos.close(); } }
额外优化建议
- 避免静态全局资源:你的
fis、workbook、fos都是静态全局变量,这种设计很容易引发资源泄漏或线程安全问题。建议改成局部变量,或者用Java的try-with-resources自动管理资源,比如加载文件时:public static void constructInputStreamForBacklogForm(int sheetInd) throws IOException { if (fis != null) { fis.close(); } // try-with-resources会自动关闭inputStream,无需手动处理 try (FileInputStream inputStream = new FileInputStream(new File(excelInputFileForBacklog))) { workbook = new XSSFWorkbook(inputStream); sheetBacklogForm = workbook.getSheetAt(sheetInd); System.out.println("excelInputFileForBacklog = " + excelInputFileForBacklog); System.out.println("sheetnya = " + workbook.getSheetName(sheetInd)); } } - 移动设备专属优化:手机的存储IO性能远低于桌面端,建议:
- 尽量避免重复创建输出文件,若业务允许可直接修改原文件(注意做好备份)
- 使用Apache POI的最新稳定版本,新版本通常会包含性能优化和bug修复
- 绝对不要在主线程执行文件操作,放到后台线程处理,避免阻塞UI
修复后预期效果
修改完成后,你的写入操作耗时会降到几百毫秒以内,移动设备上的耗时也会大幅减少,完全符合只修改2个单元格的预期性能。
内容的提问来源于stack exchange,提问作者Plain_Dude_Sleeping_Alone
相关产品推荐
相关产品推荐

