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

如何使用POI分批追加数据到Excel且不读取原有文件?

嘿,这个问题我之前帮不少踩坑的开发者捋清楚过,先给你敲个关键知识点:HSSFWorkbook对应的是旧版的.xls格式,它本身最多只能容纳65536行数据——你要写900万行,远远超出了这个格式的上限,这不仅是内存撑不住的问题,格式本身就不支持。所以第一步必须先调整文件格式,换成支持1048576行的.xlsx格式(对应POI的XSSF/SXSSF),不然根本没法实现需求。

回到你的核心诉求:无需读取原有文件,分批追加行数据。分两种场景给你具体方案:

场景1:从头开始分批写入大数据量(最常见情况)

如果是从零开始生成900万行数据,直接用POI提供的SXSSFWorkbook就可以完美解决内存问题。它是专门为大数据量设计的流式处理类,会把超出内存阈值的行自动写到临时文件,内存里只保留最近的N行,完全不需要加载任何已有数据。

示例代码如下:

// 设置内存中保留1000行,超出的自动写入临时文件
SXSSFWorkbook wb = new SXSSFWorkbook(1000);
SXSSFSheet sheet = wb.createSheet("海量数据表");

// 分批写入900万行
for (int rowNum = 0; rowNum < 9000000; rowNum++) {
    Row row = sheet.createRow(rowNum);
    // 填充单元格数据,这里以第一列为例
    row.createCell(0).setCellValue("数据行" + rowNum);
    
    // 每处理10万行手动刷新一次,释放内存(可选,SXSSF会自动处理,但手动触发更可控)
    if (rowNum % 100000 == 0) {
        ((SXSSFSheet) sheet).flushRows();
    }
}

// 写入到最终文件
try (FileOutputStream out = new FileOutputStream("海量数据.xlsx")) {
    wb.write(out);
} finally {
    // 清理临时文件,释放资源
    wb.dispose();
}

这种方式的内存占用非常低,完全不用担心OOM问题。

场景2:需要追加到已有的.xlsx文件中

如果确实需要在已存在的xlsx文件末尾追加数据,又不想把整个文件读入内存,可以借助POI的SAX解析能力+OOXML底层操作,只读取工作表的必要结构,不加载整个工作簿到内存,然后直接在XML层面追加新行。

大致实现思路如下:

  1. 打开已有xlsx的OPCPackage(xlsx本质是zip包)。
  2. 用SAX解析器读取目标工作表的XML内容,记录当前的最大行号。
  3. 直接向工作表的XML文件末尾写入新行的XML节点。
  4. 保存并关闭包。

示例代码框架(需要自定义SAX处理器):

// 打开已有xlsx文件的包
OPCPackage pkg = OPCPackage.open("已有数据.xlsx");
XSSFReader reader = new XSSFReader(pkg);
SharedStringsTable sst = reader.getSharedStringsTable();

// 获取目标工作表的输入流(需要先找到对应sheet的rId,可通过reader.getSheetsData()遍历获取)
InputStream sheetStream = reader.getSheet("rId1");

// 自定义SAX处理器,用于解析现有sheet并追加行
SheetAppendHandler appendHandler = new SheetAppendHandler(sst, pkg, "目标工作表名");
XMLReader parser = XMLReaderFactory.createXMLReader();
parser.setContentHandler(appendHandler);
parser.parse(new InputSource(sheetStream));

// 开始追加新的一批数据
for (int i = 0; i < 100000; i++) {
    appendHandler.appendRow("追加数据行" + i);
}

// 保存修改并关闭资源
pkg.save(new FileOutputStream("追加后的数据.xlsx"));
pkg.close();

这里的SheetAppendHandler需要你自己实现,继承XSSFSheetXMLHandler,重写相关方法来记录行号,并提供appendRow方法生成新行的XML内容写入到包中。这种方式需要你对OOXML的结构有一定了解,但能彻底避免加载整个文件到内存。

最后再强调一次:绝对不要用HSSF处理超过65536行的数据,格式本身的限制是硬伤,换XSSF/SXSSF才是解决问题的前提。

内容的提问来源于stack exchange,提问作者maurice

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 04:27:04