如何使用EasyExcel处理百万行级别的Excel文件

2025-04发布11次浏览

在处理百万行级别的Excel文件时,传统的Excel处理方式(如Apache POI)可能会面临内存占用过高、性能低下等问题。而阿里巴巴开源的EasyExcel框架因其轻量级、高效和易用的特点,成为了解决这一问题的理想工具。以下是使用EasyExcel处理大规模Excel文件的具体方法与注意事项。


一、EasyExcel简介

EasyExcel是基于Java语言开发的一个简单高效的Excel处理库,它通过流式读取的方式显著降低了内存占用。相比传统的Excel处理库(如Apache POI),EasyExcel更适合处理超大数据量的场景,同时提供了丰富的API支持。


二、准备工作

1. 引入依赖

首先,在项目的pom.xml中引入EasyExcel的Maven依赖:

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>3.0.5</version> <!-- 请根据实际需求选择版本 -->
</dependency>

2. 创建数据模型类

为了将Excel中的数据映射到Java对象中,需要定义一个对应的实体类。例如:

public class UserData {
    @ExcelProperty("姓名") // 对应Excel列名
    private String name;

    @ExcelProperty("年龄")
    private Integer age;

    @ExcelProperty("邮箱")
    private String email;

    // Getter和Setter方法
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

三、流式读取Excel文件

对于百万行级别的Excel文件,直接一次性加载所有数据到内存中会导致OOM(Out of Memory)。因此,推荐使用EasyExcel的分页读取逐行读取功能。

1. 实现监听器

创建一个继承自AnalysisEventListener的监听器类,用于处理每一行的数据。

public class ExcelListener extends AnalysisEventListener<UserData> {

    private List<UserData> dataList = new ArrayList<>();

    @Override
    public void invoke(UserData data, AnalysisContext context) {
        // 每读取一行数据都会调用此方法
        dataList.add(data);
        if (dataList.size() >= 1000) { // 达到一定数量后进行批量处理
            saveData(); // 调用业务逻辑保存数据
            dataList.clear(); // 清空缓存列表
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 所有数据解析完成后调用
        if (!dataList.isEmpty()) {
            saveData(); // 处理剩余未保存的数据
        }
    }

    private void saveData() {
        // 在这里实现具体的业务逻辑,比如将数据插入数据库
        System.out.println("保存了 " + dataList.size() + " 条数据");
    }
}

2. 调用读取方法

通过EasyExcel.read方法结合监听器完成文件读取:

public class ExcelReader {
    public static void main(String[] args) {
        String fileName = "path/to/large_file.xlsx"; // Excel文件路径

        EasyExcel.read(fileName, UserData.class, new ExcelListener())
                .sheet() // 默认读取第一个工作表
                .doRead();
    }
}

四、写入百万行级别的Excel文件

当需要生成大文件时,可以利用EasyExcel的分页写入功能避免内存溢出。

1. 实现数据提供器

创建一个IteratorList作为数据源:

public class LargeDataGenerator implements Iterator<UserData> {

    private int count = 0;

    @Override
    public boolean hasNext() {
        return count < 1000000; // 假设生成100万条数据
    }

    @Override
    public UserData next() {
        UserData data = new UserData();
        data.setName("User" + count);
        data.setAge(20 + count % 50);
        data.setEmail("user" + count + "@example.com");
        count++;
        return data;
    }
}

2. 写入文件

使用EasyExcel.write方法将数据写入Excel文件:

public class ExcelWriter {
    public static void main(String[] args) {
        String fileName = "path/to/output_file.xlsx";

        EasyExcel.write(fileName, UserData.class)
                .sheet("Sheet1")
                .doWrite(new LargeDataGenerator());
    }
}

五、优化建议

  1. 调整JVM参数:对于特别大的文件,适当增加堆内存大小(如-Xmx4g)。
  2. 并发处理:如果硬件条件允许,可以通过多线程并行处理数据以提升效率。
  3. 日志监控:在生产环境中,建议加入日志记录以便监控读写进度和异常情况。
  4. 数据库操作优化:在批量插入数据库时,使用事务控制和批量提交来减少IO开销。

六、总结

EasyExcel以其高效的流式读写机制,为处理百万行级别的Excel文件提供了强大支持。通过合理设计监听器和数据提供器,可以轻松应对大规模数据场景下的性能挑战。