Apache POI XSSFWorkbook 写入Excel文件的潜在风险

如果只需要 写入 Excel 文件 ,使用 XSSFWorkbook 可能会遇到以下问题,尤其是在处理 大数据量(如超过 10 万行) 时:


1. XSSFWorkbook 写入文件的主要问题

(1)内存溢出(OOM)

  • 原因 :XSSFWorkbook 会将 整个 Excel 文件(包括所有行、单元格、样式等) 全部加载到内存中。

  • 表现 :

    • 如果数据量较大(如 10 万行以上),JVM 内存可能不足,抛出 OutOfMemoryError。
    • 即使不报 OOM,内存占用也会非常高,影响系统性能。
  • 示例 :

    复制代码

    java

    复制代码
    `XSSFWorkbook workbook = new XSSFWorkbook(); // 创建空工作簿
    XSSFSheet sheet = workbook.createSheet("Sheet1");
    
    // 写入 100 万行数据(内存爆炸!)
    for (int i = 0; i < 1_000_000; i++) {
        XSSFRow row = sheet.createRow(i);
        row.createCell(0).setCellValue("Data " + i);
    }
    
    // 保存到文件(可能 OOM)
    try (FileOutputStream fos = new FileOutputStream("output.xlsx")) {
        workbook.write(fos);
    }`
    • 结果:JVM 内存耗尽,程序崩溃。

(2)性能问题

  • 写入速度慢 :
    • XSSFWorkbook 在内存中构建整个 Excel 结构,数据量大时 构建时间极长。
    • 调用 workbook.write() 时,所有数据一次性写入磁盘,I/O 压力大。
  • GC 压力 :
    • 大数据量会导致 频繁 GC(垃圾回收),进一步降低性能。

2. 替代方案:SXSSFWorkbook(推荐)

(1)为什么 SXSSFWorkbook 更适合写入大数据?

  • 流式写入(Streaming API) :
    • 仅保留 最近 N 行 (默认 100 行)在内存中,其余数据 直接写入磁盘临时文件。
    • 用 磁盘空间换内存空间,避免 OOM。
  • 内存占用低 :
    • 即使写入 100 万行数据,内存占用也几乎不变(仅保留最新几行)。
  • 性能更好 :
    • 数据逐行写入磁盘,减少内存压力和 GC 开销。

(2)SXSSFWorkbook 写入示例

复制代码

java

复制代码
`// 1. 创建 SXSSFWorkbook(保留 100 行在内存)
SXSSFWorkbook workbook = new SXSSFWorkbook(100);
SXSSFSheet sheet = workbook.createSheet("Sheet1");

// 2. 写入 100 万行数据(不会 OOM)
for (int i = 0; i < 1_000_000; i++) {
    SXSSFRow row = sheet.createRow(i);
    row.createCell(0).setCellValue("Data " + i);
    
    // 可选:手动刷新行到磁盘(减少内存占用)
    if (i % 1000 == 0) {
        ((SXSSFSheet) sheet).flushRows(100); // 保留最近 100 行
    }
}

// 3. 保存到文件
try (FileOutputStream fos = new FileOutputStream("output.xlsx")) {
    workbook.write(fos);
}

// 4. 清理临时文件(必须调用!)
workbook.dispose();`
  • 关键点 :
    • new SXSSFWorkbook(100):内存中保留 100 行,其余写入磁盘。
    • flushRows(100):手动刷新行到磁盘(可选)。
    • dispose():删除临时文件(必须调用,否则磁盘可能残留垃圾文件)。

3. 其他替代方案

(1)EasyExcel(阿里开源)

  • 优点 :

    • 基于 SAX 模式解析 Excel,几乎无内存限制。
    • API 简单,支持大数据量写入。
  • 示例 :

    复制代码

    java

    复制代码
    `// 1. 定义数据模型
    public class DemoData {
        @ExcelProperty("数据")
        private String data;
        // getters & setters
    }
    
    // 2. 写入 Excel
    List<DemoData> dataList = new ArrayList<>();
    for (int i = 0; i < 1_000_000; i++) {
        dataList.add(new DemoData("Data " + i));
    }
    
    EasyExcel.write("output.xlsx", DemoData.class)
             .sheet("Sheet1")
             .doWrite(dataList);`
  • 适用场景 :

    • 需要 极低内存占用 的大数据量写入。
    • 项目允许引入第三方库。

(2)CSV 格式(如果不需要 Excel 特性)

  • 优点 :

    • 纯文本格式,无内存问题。
    • 写入速度极快。
  • 示例 :

    复制代码

    java

    复制代码
    `try (PrintWriter pw = new PrintWriter(new FileWriter("output.csv"))) {
        for (int i = 0; i < 1_000_000; i++) {
            pw.println("Data " + i);
        }
    }`
  • 适用场景 :

    • 不需要 Excel 格式(如公式、样式、多 Sheet 等)。
    • 仅需存储结构化数据。

4. 总结

方案 内存占用 性能 适用场景
XSSFWorkbook ❌ 高(OOM 风险) ❌ 慢 小数据量(< 10 万行)
SXSSFWorkbook ✅ 低 ✅ 快 大数据量(> 10 万行)
EasyExcel ✅ 极低 ✅ 极快 大数据量 + 需要 Excel 格式
CSV ✅ 极低 ✅ 极快 不需要 Excel 特性

推荐选择

  1. 如果必须用 POI → SXSSFWorkbook(流式写入,避免 OOM)。
  2. 如果项目允许第三方库 → EasyExcel(更简单、更高效)。
  3. 如果不需要 Excel 特性 → CSV(最快、最省内存)。

⚠️ 绝对不要用 XSSFWorkbook 写入大数据! 否则必然面临 OOM 或性能崩溃问题。

相关推荐
尤鸟倦3 天前
OneNote table复制到Excel遇到的各种问题
excel
2501_930707784 天前
使用C#代码使用条件格式为 Excel 隔行设置颜色
c#·excel
leihefeng4 天前
PX04-用 Python 读 Excel 画折线图,还能直接插回 Excel 文件
python·excel
yanlaifan4 天前
Excel中指定单元格不能输入内容的方法
excel
babe小鑫4 天前
信息与计算科学专业应届生面试 怎么证明自己能解决业务问题
学习·r语言·excel
Data-Miner5 天前
商品ABC分类分析怎么用AI做?脚本复用+图表可编辑的一次完整实操
人工智能·数据分析·excel
E-iceblue7 天前
Excel 列转行/行列转换全指南:从 4 种常见解法到 Python 批量自动化
python·excel·python库·spire.xls
Data-Miner8 天前
AI处理数据的脚本复用与逻辑复用有什么区别?哪种方式更能沉淀工作成果
数据分析·excel
福兮说8 天前
在浏览器里写一个“够用就好“的 Excel 公式求值器
前端·javascript·excel·编译原理
慧都小妮子8 天前
标签打印如何减少手工抄数?用Bartender 直连 Excel 批量打印
excel·bartender·条码打印·标签打印软件·数据驱动打印·工业打印机