分块发送Excel文件仅写入前100条数据的技术问题求助
问题分析与解决方案
核心问题
- 多次写入工作簿到流:循环内每次调用
workbook.write(outputStream)会将整个工作簿的当前状态完整写入流,导致流中包含多个独立的Excel文件数据。Excel打开时仅解析第一个文件,因此只能看到前100条记录,后续数据虽在流中但无法被识别。 - 重复创建同名工作表:Excel不允许同一工作簿存在同名工作表,
sheet = workbook.createSheet("Datos")必然抛出异常。 - 错误的工作表复用逻辑:试图重新创建同名工作表而非复用原有工作表,导致数据无法累积到同一表中。
修正后的代码
@Override public void generateAndSendExcelChunks(ServletOutputStream outputStream) throws IOException { // 设置SXSSF的内存窗口大小,超过的行自动写入临时文件,降低内存占用 int rowAccessWindowSize = 100; Workbook workbook = new SXSSFWorkbook(rowAccessWindowSize); Sheet sheet = workbook.createSheet("Datos"); int totalRows = 10000; int rowsPerChunk = 100; int currentRow = 0; while (currentRow < totalRows) { int endRow = currentRow + rowsPerChunk; endRow = Math.min(endRow, totalRows); // 复用同一个工作表,分块生成数据 generateChunkData(sheet, currentRow, endRow); currentRow = endRow; } // 所有数据生成完成后,一次性写入输出流 workbook.write(outputStream); outputStream.flush(); // 清理SXSSF的临时文件 ((SXSSFWorkbook) workbook).dispose(); workbook.close(); } private void generateChunkData(Sheet sheet, int startRow, int endRow) { for (int i = startRow; i < endRow; i++) { Row row = sheet.createRow(i); Cell cell = row.createCell(0); cell.setCellValue("Valor " + (i + 1)); } }
关键修正点
- 单一工作表复用:全程使用同一个
Sheet实例,所有分块数据都写入该表,确保数据累积在同一张工作表中。 - 单次工作簿写入:仅在所有数据生成完成后调用一次
workbook.write(outputStream),保证流中只有一个完整的Excel文件数据。 - SXSSF内存优化:通过
rowAccessWindowSize参数控制内存中保留的行数,超过部分自动写入临时文件,避免大数量级数据导致内存溢出。 - 临时文件清理:调用
SXSSFWorkbook.dispose()清理生成的临时文件,防止磁盘空间泄漏。
关于"stream closed"错误的说明
原代码中尝试获取已有工作表后调用workbook.write报错,是因为第一次write操作会触发SXSSF的资源清理,后续再对工作簿进行修改或写入会导致流已关闭的异常。修正后仅单次写入,从根本上避免了该问题。
内容的提问来源于stack exchange,提问作者master
相关产品推荐
相关产品推荐

