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

EasyExcel:快速读写Excel的工具类

image

EasyExcel:快速读写Excel的工具类

项目介绍

​EasyExcel是一个基于Java的、快速、简洁、解决大文件内存溢出的Excel处理工具。
他能让你在不用考虑性能、内存的等因素的情况下,快速完成Excel的读、写等功能。

pom地址


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

快速入门


简单读

读取excel的操作,主要如下:

  1. 创建对应数据对象(映射表格中的列)
  2. 创建一个xxxListener类(可以使用匿名内部类替代)
  3. 创建输入流(或者其他io方式)
  4. 调用EasyExcel方法进行读取

test.xlsx,使用此文件进行读取,放入resources下使用

步骤一:创建数据对象

举例:DemoData

@Data
public class DemoData {private Long id;private String nickName;private Double score;
}
  • @Data是Lombok[^1]中的方法,可以快速生成setter和getter以及toString等

步骤二:创建Listener

举例:DemoDataListener

@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);/*** 每读一条数据解析就会调用此方法* @param demoData* @param analysisContext*/@Overridepublic void invoke(DemoData demoData, AnalysisContext analysisContext) {Gson gson = new Gson();log.info("解析到一条数据:{}", gson.toJson(demoData));cachedDataList.add(demoData);// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOMif (cachedDataList.size() >= BATCH_COUNT) {saveData();// 存储完成清理listcachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);}}@Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {// 这里也要保存数据,确保最后遗留的数据也存储到数据库saveData();log.info("所有数据解析完成!");}/*** 保存数据到数据库*/private void saveData() {log.info("{}条数据,开始存储数据库!", cachedDataList.size());log.info("存储数据库成功!");}}
  • Listener可以对解析的数据进行更高自由度的操作:如 写入数据到数据库

步骤三:创建输入流

接下来的代码和步骤四都是一个代码中的,此阶段为调用。

创建输入流代码块:

try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream("test.xlsx")) {...
} 
catch (Exception e) {e.printStackTrace();
}

步骤四:调用方法

tips

这里举例的是其中一种调用方法,详情请参考:完整读取代码案例

EasyExcel.read(inputStream, DemoData.class, new PageReadListener<DemoData>(dataList -> {dataList.forEach(data -> {log.info("读取到数据:{}", data);});
})).sheet().doRead();

完整读取代码案例

ReadTest.java

@Slf4j
public class ReadTest {/*** 方法1:简单读* 1. 创建excel对应的对象 参照* 2. 由于默认一行行读取excel,所以需要创建excel一行一行的回调监听器* 3. 直接读即可*/@Testpublic void simpleRead() {try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream("test.xlsx")) {EasyExcel.read(inputStream, DemoData.class, new PageReadListener<DemoData>(dataList -> {dataList.forEach(data -> {log.info("读取到数据:{}", data);});})).sheet().doRead();} catch (Exception e) {e.printStackTrace();}}/*** 方法2:简单读(匿名内部类)* 优化点:更多自定义空间,如:读取过程中添加存储到数据库* 1. 创建excel对应的对象 参照* 2. 由于默认一行行读取excel,所以需要创建excel一行一行的回调监听器* 3. 直接读即可*/@Testpublic void simpleRead2() {try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream("test.xlsx")) {EasyExcel.read(inputStream, DemoData.class, new ReadListener<DemoData>() {/*** 单次缓存数据量*/private static final int BATCH_COUNT = 100;/*** 临时存储*/private List<DemoData> cacheDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);@Overridepublic void invoke(DemoData demoData, AnalysisContext analysisContext) {cacheDataList.add(demoData);log.info("读取到数据:{}", demoData);if (cacheDataList.size() >= BATCH_COUNT) {saveData();// 存储完成清理 listcacheDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);}}@Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {saveData();}/*** 模拟存储数据库*/private void saveData() {log.info("{}条数据, 开始存储数据库!", cacheDataList.size());log.info("数据库存储成功!");}}).sheet().doRead();} catch (IOException e) {log.error("IOException: {}", e.getMessage());}}/*** 其余两个最简单的写法*/@Testpublic void simpleRead3() {try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream("test.xlsx")) {// 写法1// 由于流使用后会自动关闭,所以写法1和2要分开运行
//            EasyExcel.read(inputStream, DemoData.class, new DemoDataListener()).sheet().doRead();// 写法2try (ExcelReader excelReader = EasyExcel.read(inputStream, DemoData.class, new DemoDataListener()).build()) {// 构建一个sheet 可以指定明知或者sheetNoReadSheet sheet = EasyExcel.readSheet(0).build();// 读取excelReader.read(sheet);}} catch (IOException e) {log.error("IOException: {}", e.getMessage());}}}

指定索引或列名读取

和简单读差不多,主要修改在 Data 上,需要对映射的属性使用 @ExcelProperty 进行配置。

这里使用表格:test1.xlsx

步骤一:创建数据对象

IndexOrNameData

@Data
public class IndexOrNameData {/*** 强制读取第三个* 一般不建议 index 和 name 同时用*/@ExcelProperty(index = 2)private Double doubleData;/*** 用名字去匹配,这里需要注意,如果名字重复,会只读取第一个** @ExcelProperty("字符串标题")*/@ExcelProperty("字符串标题")private String string;@ExcelProperty("日期标题")private Date date;}

  • image

步骤二:创建Listener

IndexOrNameDataListener

@Slf4j
public class IndexOrNameDataListener extends AnalysisEventListener<IndexOrNameData> {/*** 每隔5条存储数据库,实际使用中可以100条,然后清理list ,方便内存回收*/private static final int BATCH_COUNT = 5;Gson gson = new Gson();private List<IndexOrNameData> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);@Overridepublic void invoke(IndexOrNameData data, AnalysisContext context) {log.info("解析到一条数据:{}", gson.toJson(data));cachedDataList.add(data);if (cachedDataList.size() >= BATCH_COUNT) {saveData();cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);}}@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {saveData();log.info("所有数据解析完成!");}/*** 加上存储数据库*/private void saveData() {log.info("{}条数据,开始存储数据库!", cachedDataList.size());log.info("存储数据库成功!");}
}

步骤三:创建输入流以及调用

/**
* 指定列的下标或列名* 1. 创建excel对应的实体对象,并使用{@link ExcelProperty}注解* 2. 由于默认一行行的读取excel,所以需要创建excel一行一行的回调监听器* 3. 直接读即可*/
@Test
public void indexOrNameRead() {try (InputStream in = getClass().getClassLoader().getResourceAsStream("test1.xlsx")) {EasyExcel.read(in, IndexOrNameData.class, new IndexOrNameDataListener()).sheet().doRead();} catch (IOException e) {log.error("IOException: {}", e.getMessage());}
}

文章转载自:

http://DrTqoBQw.wynyf.cn
http://kROenViA.wynyf.cn
http://XXI4e0ty.wynyf.cn
http://u7SHBTrO.wynyf.cn
http://wAaSyLe2.wynyf.cn
http://GzLk0bb3.wynyf.cn
http://0jCCZMIO.wynyf.cn
http://vDqbc30D.wynyf.cn
http://PsJ7YrLD.wynyf.cn
http://dXBHOP1d.wynyf.cn
http://WFzK6wMo.wynyf.cn
http://s5qicNAI.wynyf.cn
http://Uirg1KAd.wynyf.cn
http://zGqu6BfQ.wynyf.cn
http://4Rfahrvr.wynyf.cn
http://nnAuJRhb.wynyf.cn
http://2cNz63Jp.wynyf.cn
http://viPGrQVc.wynyf.cn
http://hlUZwFrP.wynyf.cn
http://4yqb0ezS.wynyf.cn
http://V9AdMqO4.wynyf.cn
http://f7QVbbyk.wynyf.cn
http://0XeQwc8U.wynyf.cn
http://dkpHJ5p4.wynyf.cn
http://4LvaFKHC.wynyf.cn
http://gHaaAFU5.wynyf.cn
http://iQ7cDQwS.wynyf.cn
http://efdk3eFz.wynyf.cn
http://SCZx8dgQ.wynyf.cn
http://t011eDGE.wynyf.cn
http://www.dtcms.com/a/375081.html

相关文章:

  • 基于Room+RESTful的双权限Android开机时间监控方案
  • 串口数据收发的设计
  • 基于Nginx实现反向代理、负载均衡与动静分离完整部署指南
  • Excel 表格 - Excel 单元格添加边框
  • 产品无法正确解析复杂表格和流程图,有什么替代方案或优化方法?
  • C++ -- 模板
  • C# ObjectListView实现树状文件夹浏览
  • 高级 RAG 技术原理和前沿进展
  • 42.Shell脚本判断和if语句及相关案例
  • Game Runtime Libraries Package 解决游戏运行的痛点困境
  • 《P3825 [NOI2017] 游戏》
  • 第三课、Cocos Creator 项目创建与目录结构详解
  • C#中的浅拷贝与深拷贝
  • docker 整理几个常用的指令
  • Git上有更新而本地无更新时的解决方案
  • Doc2X为一切AI文档服务的基础设施,将PDF转换为Word、HTML、LaTeX、Markdown等
  • k8s 内置的containerd配置阿里云个人镜像地址及认证
  • 新节点加入k8s集群命令查看
  • 在 PostgreSQL中查看有哪些用户
  • 【从零开始的大模型原理与实践教程】--第一章:NLP基础概念
  • 零侵入式对接美团核销接口的技术合作模式
  • Kafka面试精讲 Day 14:集群扩容与数据迁移
  • 解耦-IOCDI
  • 【秋招笔试】2025.09.07蚂蚁算法岗笔试题
  • 10月17日,博睿数据受邀出席GOPS 全球运维大会 2025 · 上海站!
  • 第三方软件测评机构:MongoDB分片集群写入吞吐量与延迟第三方性能测评
  • 【硬件-笔试面试题-76】硬件/电子工程师,笔试面试题(知识点:H桥驱动电路的设计要点)
  • 【56页PPT】数字孪生智能工厂总体结构技术架构MES+ERP建设方案(附下载方式)
  • type(类型别名)和 interface的区别和最佳实践
  • 【直流电机鲁棒控制】matlab实现H无穷大控制的直流电机鲁棒控制研究