EasyExcel 实现 Excel 读取的核心思想是基于事件驱动的监听器模式。它不会一次性将所有数据加载到内存,而是逐行解析,并通过回调函数(监听器)来处理每一行数据,非常适合处理大数据量 Excel 文件。
以下是使用 EasyExcel 读取 Excel 的基本步骤和关键代码示例:
1. 引入依赖
首先,确保你的项目(如 Maven 或 Gradle)中引入了 EasyExcel 的依赖。
Maven 依赖示例:
xml
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.3.3</version> </dependency>
2. 创建 Excel 数据对应的实体类 (Model)
创建一个 Java 类来映射 Excel 中的每一行数据。使用 @ExcelProperty
注解来指定属性对应 Excel 的哪一列。
java
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data; // 推荐使用 Lombok 简化代码
@Data // 自动生成 Getter/Setter 等方法
public class DemoData {
// 对应 Excel 的第一列(索引从 0 开始)
@ExcelProperty(index = 0)
private String name;
// 对应 Excel 的第二列
@ExcelProperty(index = 1)
private Integer age;
// 也可以通过列名来映射(如果 Excel 有表头)
@ExcelProperty(value = "出生日期")
private Date birthday;
// 其它属性...
}
3. 实现数据读取监听器 (Listener)
创建一个监听器类,继承 AnalysisEventListener<T>
,其中 T
就是你的实体类(如 DemoData
)。在这个监听器中处理解析到的数据。
java
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import java.util.ArrayList;
import java.util.List;
public class DemoDataListener extends AnalysisEventListener<DemoData> {
/** 批量处理的数据量,可根据实际业务调整 */
private static final int BATCH_COUNT = 100;
private List<DemoData> cachedDataList = new ArrayList<>();
/**
* 每解析一行数据,这个方法会被调用一次
* @param data 解析到的数据对象
* @param context 分析上下文
*/
@Override
public void invoke(DemoData data, AnalysisContext context) {
// System.out.println("解析到一条数据: " + data);
cachedDataList.add(data);
// 达到批量处理数量时,进行数据存储操作(例如:批量插入数据库)
if (cachedDataList.size() >= BATCH_COUNT) {
saveData();
// 清理缓存列表
cachedDataList = new ArrayList<>(BATCH_COUNT);
}
}
/**
* 所有数据解析完成后,这个方法会被调用
* @param context 分析上下文
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 处理剩余未达到 BATCH_COUNT 的数据
saveData();
System.out.println("所有数据解析完成!");
}
/**
* 假设的批量存储数据方法
*/
private void saveData() {
// 在这里进行业务处理,比如将 cachedDataList 批量写入数据库
System.out.println("批量存储数据" + cachedDataList.size() + "条!");
}
}
4. 执行读取操作
使用 EasyExcel.read()
方法启动读取流程。
示例:异步(推荐)
这是处理大文件推荐的方式,它利用监听器模式逐行处理数据,内存占用小。
java
import com.alibaba.excel.EasyExcel;
import java.io.File;
public class ExcelReadExample {
public static void simpleRead(String fileName) {
// fileName 可以是文件路径、File 对象、InputStream 等
EasyExcel.read(
fileName,
DemoData.class, // 实体类
new DemoDataListener() // 监听器
)
.sheet() // 默认读取第一个 Sheet
.headRowNumber(1) // 从 Excel 的第几行开始读取数据(默认表头占一行,即从第 2 行开始是数据)
.doRead();
System.out.println("读取任务已提交,等待监听器处理完成...");
}
}
示例:同步读取 (不推荐大文件使用)
如果文件较小,也可以使用同步读取,它会一次性返回所有数据到一个 List
中,但可能会占用大量内存。
java
import com.alibaba.excel.EasyExcel;
import java.util.List;
import java.util.Map;
public class ExcelReadExample {
public static void synchronousRead(String fileName) {
// 1. 读取为实体类列表
List<DemoData> list = EasyExcel.read(fileName)
.head(DemoData.class)
.sheet()
.doReadSync(); // 同步读取
// 2. 也可以读取为 List<Map<Integer, String>>,不指定实体类
List<Map<Integer, String>> listMap = EasyExcel.read(fileName)
.sheet()
.doReadSync();
// 处理数据...
System.out.println("同步读取到数据条数:" + list.size());
}
}
总结要点:
- Model (实体类) :使用
@ExcelProperty
映射列。 - Listener (监听器) :实现
AnalysisEventListener
,在invoke()
中处理每行数据,在doAfterAllAnalysed()
中进行收尾工作。 - Read (读取) :使用
EasyExcel.read()
指定文件、实体类和监听器,调用.sheet().doRead()
或.doReadSync()
启动。
使用 监听器模式(异步读取) 是 EasyExcel 推荐的方式,因为它能有效地避免 OOM(内存溢出)问题。