【Java实现 通过Easy Excel完成对excel文本数据的读写】

Java实现 通过Easy Excel完成对excel文本数据的读写

  • [EasyExcel 官网概述](#EasyExcel 官网概述)
  • [1. 准备工作](#1. 准备工作)
    • [1.1 添加依赖](#1.1 添加依赖)
    • [1.2 创建模型类](#1.2 创建模型类)
    • [1.3 最简单的读的监听器(参考官网)](#1.3 最简单的读的监听器(参考官网))
  • [2. 读取Excel文件](#2. 读取Excel文件)
    • [2.1 核心原理](#2.1 核心原理)
    • [2.2 基础读取](#2.2 基础读取)
    • [2.3 读多个sheet](#2.3 读多个sheet)
    • [2.4 错误处理](#2.4 错误处理)
  • [3. 写入Excel文件](#3. 写入Excel文件)
    • [3.1 基础写入](#3.1 基础写入)

EasyExcel 官网概述

Java解析、生成Excel比较有名的框架有Apache poi、jxl。但他们都存在一个严重的问题就是非常的耗内存,poi有一套SAX模式的API可以一定程度的解决一些内存溢出的问题,但POI还是有一些缺陷,比如07版Excel解压缩以及解压后存储都是在内存中完成的,内存消耗依然很大。

easyexcel重写了poi对07版Excel的解析,一个3M的excel用POI sax解析依然需要100M左右内存,改用easyexcel可以降低到几M,并且再大的excel也不会出现内存溢出;03版依赖POI的sax模式,在上层做了模型转换的封装,让使用者更加简单方便。

1. 准备工作

1.1 添加依赖

xml 复制代码
<dependency>
    <groupId>com.alibaba.easyexcel</groupId>
    <artifactId>easyexcel</artifactId>
    <version>4.0.3</version> 
</dependency>

查看最新版本

1.2 创建模型类

Excel 中的数据需要映射到 Java 对象,先创建一个模型类。

java 复制代码
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Getter;
import lombok.Setter;

/**
 * @author: gaokelai
 * @date: 2025/1/23
 */
@Getter
@Setter
public class Weather {

    /**
     * 地区
     */
    @ExcelProperty("地区")
    private String cityName;

    /**
     * 时间
     */
    @ExcelProperty("时间")
    private String fxTime;

    /**
     * 天气
     */
    @ExcelProperty("天气")
    private String text;

    /**
     * 温度℃
     */
    @ExcelProperty("温度℃")
    private String temp;

    /**
     * 降水量
     */
    @ExcelProperty("降水量")
    private String precip;

    /**
     * 风向
     */
    @ExcelProperty("风向")
    private String windDir;

    /**
     * 风力
     */
    @ExcelProperty("风力")
    private String windScale;

    /**
     * 风速
     */
    @ExcelProperty("风速")
    private String windSpeed;

    /**
     * 气压
     */
    @ExcelProperty("气压")
    private String pressure;

    /**
     * 湿度
     */
    @ExcelProperty("湿度")
    private String humidity;

}

1.3 最简单的读的监听器(参考官网)

java 复制代码
// 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
@Slf4j
public class DemoDataListener implements ReadListener<DemoData> {

    /**
     * 每隔5条存储数据库,实际使用中可以100条,然后清理list ,方便内存回收
     */
    private static final int BATCH_COUNT = 100;
    /**
     * 缓存的数据
     */
    private List<DemoData> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
    /**
     * 假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。
     */
    private DemoDAO demoDAO;

    public DemoDataListener() {
        // 这里是demo,所以随便new一个。实际使用如果到了spring,请使用下面的有参构造函数
        demoDAO = new DemoDAO();
    }

    /**
     * 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
     *
     * @param demoDAO
     */
    public DemoDataListener(DemoDAO demoDAO) {
        this.demoDAO = demoDAO;
    }

    /**
     * 这个每一条数据解析都会来调用
     *
     * @param data    one row value. Is is same as {@link AnalysisContext#readRowHolder()}
     * @param context
     */
    @Override
    public void invoke(DemoData data, AnalysisContext context) {
        log.info("解析到一条数据:{}", JSON.toJSONString(data));
        cachedDataList.add(data);
        // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
        if (cachedDataList.size() >= BATCH_COUNT) {
            saveData();
            // 存储完成清理 list
            cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
        }
    }

    /**
     * 所有数据解析完成了 都会来调用
     *
     * @param context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 这里也要保存数据,确保最后遗留的数据也存储到数据库
        saveData();
        log.info("所有数据解析完成!");
    }

    /**
     * 加上存储数据库
     */
    private void saveData() {
        log.info("{}条数据,开始存储数据库!", cachedDataList.size());
        demoDAO.save(cachedDataList);
        log.info("存储数据库成功!");
    }
}

2. 读取Excel文件

2.1 核心原理

EasyExcel 使用了 SAX 解析器来解析 Excel 文件,这是一种事件驱动的解析方式,能够逐行读取数据而不需要一次性加载整个文档到内存中,同时通过流式读取减少了内存占用,提高了性能。

2.2 基础读取

基础读取是最简单的读取方式,适合小文件或测试环境:

java 复制代码
	/**
     * 最简单的读
     * <p>
     * 1. 创建excel对应的实体对象 Weather 
     * <p>
     * 2. 直接读即可
     */
    public void basicRead() {
        String fileName = "E:\\逐小时天气\\BeiJing-2024-01.xlsx";
		// 这里默认每次会读取100条数据 然后返回过来 直接调用使用数据就行
        // 具体需要返回多少行可以在`PageReadListener`的构造函数设置
        EasyExcel.read(fileName, Weather.class, new PageReadListener<Weather>(dataList -> {
            for (Weather weather: dataList) {
                System.out.println(JSON.toJSONString(weather)); 
            }
        })).sheet().doRead();
    }
}

2.3 读多个sheet

java 复制代码
    /**
     * 读多个或者全部sheet,这里注意一个sheet不能读取多次,多次读取需要重新读取文件
     * <p>
     * 1. 创建excel对应的实体对象 Weather 
     * <p>
     * 2. 由于默认一行行的读取excel,所以需要创建excel一行一行的回调监听器 DemoDataListener
     * <p>
     * 3. 直接读即可
     */
    public void repeatedRead() {
        String fileName = "E:\\逐小时天气\\BeiJing-2024-01-2024-10.xlsx";
        // 读取全部sheet
        // 这里需要注意 DemoDataListener的doAfterAllAnalysed 会在每个sheet读取完毕后调用一次。然后所有sheet都会往同一个DemoDataListener里面写
        EasyExcel.read(fileName, Weather.class, new DemoDataListener()).doReadAll();

        // 读取部分sheet
        fileName = "E:\\逐小时天气\\BeiJing-2024-01-2024-10.xlsx";

        try (ExcelReader excelReader = EasyExcel.read(fileName).build()) {
            // 这里为了简单 所以注册了 同样的head 和Listener 自己使用功能必须不同的Listener
            ReadSheet readSheet1 =
                EasyExcel.readSheet(0).head(Weather.class).registerReadListener(new DemoDataListener()).build();
            ReadSheet readSheet2 =
                EasyExcel.readSheet(1).head(Weather.class).registerReadListener(new DemoDataListener()).build();
            // 这里注意 一定要把sheet1 sheet2 一起传进去,不然有个问题就是03版的excel 会读取多次,浪费性能
            excelReader.read(readSheet1, readSheet2);
        }
    }

2.4 错误处理

当进行读取操作时,应该考虑可能出现的异常情况,并适当处理它们:

java 复制代码
	try {
	    basicRead();
	    //repeatedRead();
	} catch (Exception e) {
	    e.printStackTrace();
	    // 处理异常逻辑
	}

3. 写入Excel文件

3.1 基础写入

java 复制代码
	public void basicWrite() {
        String fileName = "E:\\逐小时天气\\newDataDemo.xlsx";

        // 创建要写入的数据列表
        List<Weather> list = new ArrayList<>();
        list.add(new Weather("北京", "2025/01/23 08:00:00", "晴","18","0","东北风","1","3","996","87"));
		list.add(new Weather("北京", "2025/01/23 09:00:00", "晴","18","0","东北风","1","3","996","87"));
		list.add(new Weather("北京", "2025/01/23 10:00:00", "晴","18","0","东北风","1","3","996","87"));
        // 写入 Excel 文件
        EasyExcel.write(fileName, UserData.class).sheet("天气信息").doWrite(list);
    }

高级写法及其他写入Excel技巧参考官网 Easy Excel

相关推荐
这周也會开心10 分钟前
云服务器安装JDK、Tomcat、MySQL
java·服务器·tomcat
hrrrrb1 小时前
【Spring Security】Spring Security 概念
java·数据库·spring
小信丶1 小时前
Spring 中解决 “Could not autowire. There is more than one bean of type“ 错误
java·spring
周杰伦_Jay2 小时前
【Java虚拟机(JVM)全面解析】从原理到面试实战、JVM故障处理、类加载、内存区域、垃圾回收
java·jvm
摇滚侠3 小时前
Spring Boot 3零基础教程,IOC容器中组件的注册,笔记08
spring boot·笔记·后端
程序员小凯6 小时前
Spring Boot测试框架详解
java·spring boot·后端
豐儀麟阁贵6 小时前
基本数据类型
java·算法
_extraordinary_6 小时前
Java SpringMVC(二) --- 响应,综合性练习
java·开发语言
程序员 Harry7 小时前
深度解析:使用ZIP流式读取大型PPTX文件的最佳实践
java
程序员小凯7 小时前
Spring Boot缓存机制详解
spring boot·后端·缓存