You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

分块发送Excel文件仅写入前100条数据的技术问题求助

问题分析与解决方案

核心问题

  1. 多次写入工作簿到流:循环内每次调用workbook.write(outputStream)会将整个工作簿的当前状态完整写入流,导致流中包含多个独立的Excel文件数据。Excel打开时仅解析第一个文件,因此只能看到前100条记录,后续数据虽在流中但无法被识别。
  2. 重复创建同名工作表:Excel不允许同一工作簿存在同名工作表,sheet = workbook.createSheet("Datos")必然抛出异常。
  3. 错误的工作表复用逻辑:试图重新创建同名工作表而非复用原有工作表,导致数据无法累积到同一表中。

修正后的代码

@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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 13:33:16