200万条TXT转XLSX失败求助:BufferedReader+SXSSFWorkbook无输出
解决200万条TXT记录转XLSX未生成文件的问题
我来帮你排查下为啥用BufferedReader+SXSSFWorkbook处理大数量记录时没生成XLSX文件,再给你一套经得住考验的实现方案。
常见的坑(也是你可能遇到的问题)
- 未正确完成写入流程:SXSSF是流式写入,必须显式调用
write()和close(),否则缓存的内容根本不会落地到磁盘,甚至会生成空文件/损坏文件。 - 内存溢出导致程序静默崩溃:你把所有200万条数据都存在
allRowAndColData这个大集合里,内存直接爆掉,程序还没走到写入步骤就挂了,自然没文件。 - 异常未捕获:读取或写入过程中出了问题(比如分隔符解析错误、磁盘满了、权限不够),但没加try-catch,程序直接终止,连错误信息都看不到。
- SXSSF临时文件问题:默认SXSSF会把超出内存的行写到系统临时目录,如果这个目录没权限或空间不足,也会导致写入失败。
修正后的完整代码
这套代码采用边读边写+批量刷新的方式,完全避免内存溢出,同时保证资源正确释放:
import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.streaming.SXSSFWorkbook; import java.io.*; import java.util.ArrayList; import java.util.List; public class TxtToXlsxConverter { // 每1万行刷一次磁盘,平衡内存占用和写入效率 private static final int BATCH_SIZE = 10000; // 替换成你的TXT分隔符,比如制表符用"\t" private static final String SEPARATOR = ","; public static void main(String[] args) { String txtInputPath = "your_input.txt"; String xlsxOutputPath = "your_output.xlsx"; // 用try-with-resources自动管理资源,不用手动关流,避免泄漏 try (BufferedReader txtReader = new BufferedReader(new FileReader(txtInputPath)); SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook(1000); // 内存仅保留1000行,其余写临时文件 FileOutputStream fos = new FileOutputStream(xlsxOutputPath)) { Sheet dataSheet = sxssfWorkbook.createSheet("批量数据"); int currentRowNum = 0; // 处理表头(如果你的TXT没有表头,直接注释这段) String headerLine = txtReader.readLine(); if (headerLine != null) { Row headerRow = dataSheet.createRow(currentRowNum++); String[] headerFields = headerLine.split(SEPARATOR); for (int col = 0; col < headerFields.length; col++) { Cell cell = headerRow.createCell(col); cell.setCellValue(headerFields[col].trim()); } } String currentLine; List<Row> batchRows = new ArrayList<>(BATCH_SIZE); // 边读边写,不缓存全量数据 while ((currentLine = txtReader.readLine()) != null) { String[] rowFields = currentLine.split(SEPARATOR); Row dataRow = dataSheet.createRow(currentRowNum++); for (int col = 0; col < rowFields.length; col++) { Cell cell = dataRow.createCell(col); cell.setCellValue(rowFields[col].trim()); } batchRows.add(dataRow); // 达到批量阈值,刷入磁盘并清空缓存 if (batchRows.size() >= BATCH_SIZE) { sxssfWorkbook.flushRows(); batchRows.clear(); } } // 处理最后一批不足BATCH_SIZE的行 if (!batchRows.isEmpty()) { sxssfWorkbook.flushRows(); } // 最终写入文件 sxssfWorkbook.write(fos); System.out.println("转换完成!XLSX文件路径:" + xlsxOutputPath); } catch (IOException e) { // 打印异常堆栈,快速定位问题 e.printStackTrace(); System.err.println("转换失败:" + e.getMessage()); } } }
关键优化点说明
- 流式处理,不缓存全量数据:不再用大集合存所有行,读一行写一行,内存占用始终很低,200万条也不会爆内存。
- 批量刷新磁盘:每1万行调用
flushRows()把内存中的行刷到临时文件,避免内存堆积。 - 自动资源管理:try-with-resources会自动关闭所有流和Workbook,确保
close()被调用(SXSSF的close()会清理临时文件,避免垃圾残留)。 - 异常捕获:捕获IOException并打印堆栈,能快速排查比如文件不存在、权限不足、分隔符错误等问题。
额外注意事项
- 复杂分隔符处理:如果你的TXT是带引号的CSV(比如字段里包含分隔符),不要直接用
split(),建议用Apache Commons CSV或OpenCSV来解析,避免拆分错误。 - 自定义临时目录:如果系统临时目录空间不足,可在代码开头添加
System.setProperty("java.io.tmpdir", "/path/to/your/temp/folder")指定临时目录。 - 依赖版本:确保Apache POI版本在3.8以上(SXSSF从3.8开始支持),推荐用最新稳定版(比如5.2.3)。
- 磁盘空间:200万条记录的XLSX文件大概几十到上百MB,确保输出路径有足够空间。
内容的提问来源于stack exchange,提问作者Divya Murugan
相关产品推荐
相关产品推荐

