当前位置: 首页 > article >正文

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

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

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

<dependency>
    <groupId>com.alibaba.easyexcel</groupId>
    <artifactId>easyexcel</artifactId>
    <version>4.0.3</version> 
</dependency>

查看最新版本

1.2 创建模型类

Excel 中的数据需要映射到 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 最简单的读的监听器(参考官网)

// 有个很重要的点 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 基础读取

在这里插入图片描述

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

	/**
     * 最简单的读
     * <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

    /**
     * 读多个或者全部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 错误处理

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

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

3. 写入Excel文件

3.1 基础写入

	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


http://www.kler.cn/a/516680.html

相关文章:

  • WIN11 UEFI漏洞被发现, 可以绕过安全启动机制
  • 【高项】5.5 确认范围 ITTO 、 5.6 控制范围 ITTO
  • JAVA毕业设计210—基于Java+Springboot+vue3的中国历史文化街区管理系统(源代码+数据库)
  • 客户案例:向导ERP与金蝶云星空集成方案
  • 16_动态提示窗口_协程延时
  • 博客搭建 — GitHub Pages 部署
  • 递归的本质
  • Rman还原
  • Yii框架中的Cart组件:实现购物车功能
  • GC(垃圾回收)的分类
  • 使用 Elasticsearch 导航检索增强生成图表
  • linux-centosubuntu本地源配置
  • 蓝桥杯练习日常|c/c++竞赛常用库函数
  • 使用Python爬虫获取1688店铺所有商品信息的完整指南
  • C#高级:常用的扩展方法大全
  • ubuntu系统docker环境搭建
  • STM32调试手段:重定向printf串口
  • 重载C++运算符
  • salesforce FIELD_FILTER_VALIDATION_EXCEPTION
  • LVGL+FreeRTOS实战项目:智能健康助手(蓝牙模块篇)
  • 假期day1
  • NPM 与 Node.js 版本兼容问题:npm warn cli npm does not support Node.js
  • 文献阅读 250123-Accelerated dryland expansion under climate change
  • 从 TCP/IP 演进看按序流与性能
  • tortoiseSVN图标缺少绿色钩/tortoiseSVN图标不显示解决方案
  • EDI安全:2025年数据保护与隐私威胁应对策略