Excel文件解析 - SAX和DOM方式的区别

很好的问题!这两种方式的核心区别在于解析模式内存占用。让我详细对比一下:

两种解析方式的本质区别

第一种方式(SAX 流式解析)

java 复制代码
pkg = OPCPackage.open(data);
XSSFReader reader = new XSSFReader(pkg);
XMLReader parser = XMLReaderFactory.createXMLReader(...);
parser.parse(sheetSource);
  • SAX (Simple API for XML):事件驱动,边读边处理
  • 内存占用:极低,只保留当前处理的数据
  • 处理速度:快,不需要等待整个文件加载完成

第二种方式(DOM 解析)

java 复制代码
Workbook workbook = WorkbookFactory.create(inputStream);
Sheet sheet = workbook.getSheetAt(0);
  • DOM (Document Object Model):把整个文档树加载到内存
  • 内存占用非常高,整个 Excel 文件都在内存中
  • 处理速度:慢,需要先加载整个文件

内存占用对比表

文件大小 SAX 方式 DOM 方式
1 MB ~10 MB ~50 MB
10 MB ~20 MB ~500 MB
100 MB ~50 MB ~5 GB+ ⚠️

为什么推荐第一种方式

1. 内存安全

java 复制代码
// 第二种方式的风险
Workbook workbook = WorkbookFactory.create(inputStream);
// 如果文件是 100MB,内存可能暴涨到 5GB+,直接 OOM!

2. 适合大文件场景

  • Excel 导入功能通常处理几千到几十万行数据
  • 使用 SAX 方式可以轻松处理百万行数据
  • 使用 DOM 方式可能 5 万行就内存溢出

3. 响应更快

java 复制代码
// SAX:立即开始处理第一行
parser.parse(sheetSource);  // 边读边处理

// DOM:必须等待整个文件加载完
Workbook workbook = WorkbookFactory.create(inputStream);  // 等待...
Sheet sheet = workbook.getSheetAt(0); // 等待...

第二种方式什么时候可以用?

虽然第一种方式更好,但第二种方式在以下场景也可以用:

  1. 小文件场景(< 1MB,< 1000行)
  2. 需要随机访问(比如跳到第 1000 行再回来看第 10 行)
  3. 需要修改 Excel 文件(SAX 是只读的)
  4. 读写混合操作(比如读取数据后修改某些单元格)

实际案例对比

假设用户上传一个 50MB 的 Excel 文件(约 10 万行数据):

使用第二种方式(DOM)

复制代码
1. 加载文件到内存 → 内存占用 2GB+
2. 读取数据 → 继续占用内存
3. 如果并发 5 个用户 → 10GB+ 内存
4. 结果:服务器 OOM,服务崩溃 ❌

使用第一种方式(SAX)

复制代码
1. 流式读取 → 内存占用 50MB
2. 边读边处理 → 内存稳定
3. 并发 5 个用户 → 250MB 内存
4. 结果:稳定运行 ✅

总结

维度 SAX 方式(推荐) DOM 方式(谨慎使用)
内存占用 ⭐⭐⭐⭐⭐ 极低 ⭐ 极高
处理大文件 ⭐⭐⭐⭐⭐ 优秀 ⭐ 容易 OOM
读取速度 ⭐⭐⭐⭐⭐ 快 ⭐⭐⭐ 慢
随机访问 ⭐ 不支持 ⭐⭐⭐⭐⭐ 支持
代码复杂度 ⭐⭐⭐ 稍复杂 ⭐⭐⭐⭐⭐ 简单

结论 :如果你的场景是批量导入大 Excel 文件 ,一定要用第一种 SAX 方式。如果是小文件且需要随机访问,第二种方式也可以考虑。

相关推荐
疯狂小猫咪2 小时前
中小培训机构教务数字化踩坑复盘|从 Excel 过渡到教务系统经验总结
小程序·excel
mldong4 小时前
引擎从不发一条消息:jeeflow 的两类扩展点与消息模块的分工
java·架构
君顾14 小时前
智慧零售实战指南:从技术架构到落地方案全解析
java·开发语言·零售
zhanghe6875 小时前
es的密码带有特殊字符,导出
java
梦曦i5 小时前
@meng-xi/create-uni-app vs unibest:轻量脚手架与重型框架的定位之争
前端·uni-app
平头哥技术团队5 小时前
Day 10 | 工欲善其事:VS Code 配置与项目归档
android·开发语言·前端·javascript·html·交互
pnoker5 小时前
IoT DC3 概念解读:把设备抽象成一套语义模板——位号、指令、事件与面向智能体的设备建模
java·人工智能·物联网·iot·dc3
my_realmy5 小时前
Java SE 基础学习笔记(一):面向对象、继承多态、抽象接口与异常(JDK 8)
java·多线程·并发··生产者消费者模式
乌恩大侠5 小时前
GH200 新增 NVMe SSD 分区、格式化与挂载完整流程
运维·服务器·前端
天远数科6 小时前
风险治理实战:基于天远车信盟出险构建自动化理赔核保流水线
java·网络·人工智能·自动化