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://www.pswp.cn/pingmian/95957.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/95957.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WSL Ubuntu Docker 代理自动配置教程

WSL Ubuntu Docker 代理自动配置教程 WSL Ubuntu Docker 代理自动配置教程 背景说明 在 WSL2 环境下使用 Docker 时&#xff0c;由于网络环境限制&#xff0c;经常需要通过 Windows 主机上的代理来访问 Docker Hub。但每次 Windows 重启后&#xff0c;WSL 获取到的主机 IP 地址…

踩坑实录:Django继承AbstractUser时遇到的related_name冲突及解决方案

一、问题现象分析 咱们在用Django开发时&#xff0c;有时候需要扩展用户模型&#xff0c;就会去继承AbstractUser。但这么做的时候&#xff0c;要是没处理好groups和user_permissions这两个多对多字段的反向查询名称&#xff0c;就会遇到这样的报错&#xff1a;主要就是这种错误…

push pop 和 present dismiss

push/pop 和 present/dismiss 文章目录push/pop 和 present/dismiss前言push / poppresent普通的present多层present多层present后的父子关系问题多层弹出会遇到的问题showViewController 和 showDetailViewControllershowViewControllershowDetailViewControllerdismiss模态化…

服务器异常负载排查手册 · 隐蔽进程篇

适用范围 适用于 Linux 3.10 生产环境&#xff0c;发现 load 高但用户态 CPU 接近 0 % 的场景。1. 现场冻结目标&#xff1a;在 rootkit 干预前保存易失数据。#!/bin/bash # freeze.sh TS$(date %s) mkdir -p /srv/ir/${TS} cd /srv/ir/${TS}# 1.1 进程树&#xff08;busybox 静…

2024理想算法岗笔试笔记

要理解指令微调&#xff08;Instruction Tuning&#xff09;&#xff0c;需要先将其置于大语言模型&#xff08;LLM&#xff09;的训练框架中 —— 它并非模型训练的起点&#xff0c;而是针对 “让模型更懂人类需求” 的关键优化步骤。简单来说&#xff0c;指令微调是通过让模型…

Oracle 11g离线安装依赖包完整解决方案

本文还有配套的精品资源&#xff0c;点击获取 简介&#xff1a;Oracle 11g是一款广泛使用的关系型数据库管理系统&#xff0c;在离线环境下安装时需依赖多个系统库和工具。本“oracle11g依赖包”压缩文件包含了在CentOS 7.7上安装Oracle 11g可能缺失的关键依赖RPM包&#xf…

VBA数据结构选型:效率差5倍的生死抉择

VBA性能生死局&#xff1a;Dictionary与Collection效率差5倍&#xff01;90%开发者用反血亏“你以为Collection是VBA的‘轻量级选手’&#xff1f;大错特错&#xff01;实测数据显示&#xff1a;在10万级数据循环中&#xff0c;Dictionary的查询速度比Collection快5倍&#xff…

电机控制(四)-级联PID控制器与参数整定(MATLABSimulink)

PID算法 普通PID&#xff08;Proportional-Integral-Derivative&#xff09; 通过比例&#xff08;P&#xff09;、积分&#xff08;I&#xff09;和微分&#xff08;D&#xff09;三项来进行控制 比例项&#xff08;P&#xff09;&#xff1a;根据当前误差&#xff08;目标值…

数据结构深度解析:二叉树的基本原理

在数据结构体系中&#xff0c;树是一种重要的非线性层次结构&#xff0c;它通过 “节点” 与 “边” 的连接关系&#xff0c;模拟了现实世界中树的分支结构&#xff0c;能够高效地解决数据的查找、插入、删除等问题。而二叉树作为树结构中最简单、应用最广泛的类型&#xff0c;…

【React】Ant Design 5.x 实现tabs圆角及反圆角效果

需要实现的效果实现思路 利用tab页的before和after属性&#xff0c;添加tab页前后的圆弧属性&#xff0c;同时使用tab页的shadow阴影填充右下角的圆弧空缺部分。<TabsonChange{onChange}type"card"items{getTabItems()}/>.ant-tabs-nav{margin: 0;.ant-tabs-na…

WordPress过滤文章插入链接rel属性noopener noreferrer值

WordPress过滤文章插入链接rel属性noopener noreferrer值在保存文章的时候&#xff0c;WordPress会自动过滤文章内容中的链接&#xff0c;具有target属性的链接会自动添加rel"noopener noreferrer"&#xff0c;该属性是为了预防跨站攻击&#xff0c;站内链接似乎没有…

make_shared的使用

目录 1. make_shared 的基本概念 基本用法 2. 引入 make_shared 的主要原因 2.1 解决传统构造方式的问题 2.2 标准委员会的动机 3. make_shared 的核心优势 3.1 性能优势&#xff08;最重要优点&#xff09; 内存分配优化&#xff1a; 性能提升表现&#xff1a; 3.2 异…

基于 Gemini 的 CI/CD 自动化测评 API 集成实战教程

在现代软件开发中&#xff0c;CI/CD 集成 已经成为必不可少的流程。它不仅能帮助团队快速迭代&#xff0c;还能通过自动化手段提升代码质量。而在编程培训和团队内部学习中&#xff0c;如何引入 自动化测评 API&#xff0c;实现提交即测评、即时反馈呢&#xff1f;本文将以 Gem…

SOME/IP-SD(Service Discovery)协议的核心协议

<摘要> 本解析以AutoSAR AP R22-11版本为基准&#xff0c;全面系统地阐述了SOME/IP-SD&#xff08;Service Discovery&#xff09;协议的核心内容。从车载网络演进背景切入&#xff0c;详细剖析了面向服务架构&#xff08;SOA&#xff09;下服务发现的必要性&#xff0c;…

视频串行解串器(SerDes)介绍

视频串行解串器&#xff08;SerDes&#xff09;是高速数据通信中的核心接口技术&#xff0c;通过串行化与解串行化实现视频信号的高效传输&#xff0c;广泛应用于汽车电子、数据中心、高清视频传输等领域。 一、技术原理串行化&#xff08;Serializer&#xff09; 功能&#xf…

哈士奇vs网易高级数仓:数据仓库的灵魂是模型、数据质量还是计算速度?| 易错题

面试场景 面试官: (微笑,营造轻松但专业的氛围)嗨,哈士奇,欢迎来参加网易的二面。我看你简历上数据仓库的项目经验很丰富,我们今天就深入聊聊。我这里有一个经典的问题想听听你的看法:在你看来,数据仓库的灵魂是模型、数据质量还是计算速度? 哈士奇: (不假思索,…

贪心算法应用:3D打印支撑结构问题详解

Java中的贪心算法应用&#xff1a;3D打印支撑结构问题详解 1. 问题背景与概述 1.1 3D打印中的支撑结构问题 在3D打印过程中&#xff0c;当模型存在悬空部分&#xff08;overhang&#xff09;时&#xff0c;通常需要添加支撑结构&#xff08;support structure&#xff09;来防止…

Python爬虫实战:研究3D plotting模块,构建房地产二手房数据采集和分析系统

1. 引言 1.1 研究背景 在大数据与人工智能技术快速发展的背景下,数据已成为驱动决策的核心要素。互联网作为全球最大的信息载体,蕴含海量结构化与非结构化数据,如何高效提取并分析这些数据成为学术界与产业界的研究热点。 网络爬虫技术通过自动化请求与解析网页,实现数据…

Gradio全解10——Streaming:流式传输的音频应用(7)——ElevenLabs:高级智能语音技术

Gradio全解10——Streaming&#xff1a;流式传输的音频应用&#xff08;7&#xff09;——ElevenLabs&#xff1a;高级智能语音技术10.7 ElevenLabs&#xff1a;高级智能语音技术10.7.1 核心功能与可用模型1. 核心功能与产品2. 三类语音模型10.7.2 文本转语音API1. 完整操作步骤…

【桃子同学笔记4】PCIE训练状态机(LTSSM)基础

首先&#xff0c;所谓LTSSM&#xff0c;即&#xff1a;Link Training and Status State Machine&#xff08;链路训练及状态机&#xff09; 下图为 LTSSM 的状态机及训练过程&#xff1a; LTSSM 包含 11 个顶层状态&#xff1a;Detect、Polling、Configuration、Recovery、L0、…