java 读取 Excel 文件(一行一行读取)

Excel 文件数据量过大,一次读取到内存中会造成资源浪费,严重的会使服务器宕机,所以读取一行处理一行,或者读取一定的行数进行处理,上代码
我用的是阿里的EasyExcel
maven:

      com.alibabaeasyexcel2.2.6

使用 EasyExcel 行读取必须继承监听器,生成公共的Listener

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import java.util.ArrayList;
import java.util.List;/*** @version 1.0* @author: lsy* @create: 2021-05-28 11:17**//***  公共的BaseListener*/
public abstract class BaseListener extends AnalysisEventListener {/*** 每隔3000条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收*/private static final int BATCH_COUNT = 3000;List list = new ArrayList();public abstract void invoke(T var1, AnalysisContext analysisContext);public abstract void saveData();public abstract void doAfterAllAnalysed(AnalysisContext analysisContext);
}

因为每种 Excel 要写不同的逻辑就直接继承这个公共的,重新读取方法就行

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.exception.ExcelAnalysisException;
import com.kdmins.pojo.User;
import lombok.extern.slf4j.Slf4j;import java.util.ArrayList;
import java.util.List;
import java.util.Map;/*** @version 1.0* @author: lsy* @create: 2021-05-31 09:48**/
@Slf4j  //日志框架
public class TestListener extends BaseListener {/*** 每隔100条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收*/private static final int BATCH_COUNT = 100;//存放数据信息的集合List list = new ArrayList<>(100);/*** 读取表头的方法,默认设置的第一行为表头,多行可自行设置** @param headMap* @param context*/@Overridepublic void invokeHeadMap(Map headMap, AnalysisContext context) {log.info("进入校验表头方法");//把表头全部读取拼接成字符串进行比对StringBuilder stringBuilder = new StringBuilder();for (Map.Entry map : headMap.entrySet()) {stringBuilder.append(map.getValue().trim());}log.info("表头="+stringBuilder.toString());//校验表头,不是则抛出异常 (这里应该是一个常量,或者动态生成的表头: 建议动态生成后传入)if (!stringBuilder.toString().equals("姓名密码")) {log.error("表头对比错误 ,表头数据为:{}", headMap);//easyExcel 内业务异常必须抛 ExcelAnalysisStopException 才能被接收到throw new ExcelAnalysisException("表头数据对比错误,请使用标准的Excel模板上传");}//todo 所有在读取数据之前的逻辑都可以写在这里}/*** Excel 读取器,一行一行读取* @param var1    每一行的数据* @param analysisContext*/@Overridepublic void invoke(User var1, AnalysisContext analysisContext) {log.info("获取到数据为:"+var1.toString());list.add(var1);// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOMif (list.size() >= BATCH_COUNT) {saveData();// 存储完成清理 listlist.clear();}}/*** 存储数据到数据库*/@Overridepublic void saveData() {//todo 循环存储 , 因为 Listener是new出来的没有交给spring管理,所以要用构造方法把mapper传进来,具体请百度//todo 循环插入数据库的方法log.info("执行数据入库方法");}/*** 收尾方法,把不足 BATCH_COUNT 的存入数据库* 因为我们是100条存一次数据库,如果最后剩余50条则在此方法处理** @param analysisContext*/@Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {//todo 不足100条的也存进数据库//todo insert 方法log.info("执行数据入库方法");}
} 

实体类:

import lombok.Data;/*** @version 1.0* @author: lsy* @create: 2021-05-31 09:48**/
@Data
public class User {//Excel 表头@ExcelProperty(value = "姓名", index = 0)private String name;//Excel 表头@ExcelProperty(value = "密码", index = 1)private String password;
}

这是我创建的测试Excel
在这里插入图片描述

测试main方法:

@Slf4j
public class TestDemo {public static void main(String[] args) {log.info("读取开始");File file = new File("C:\\Excel\\User.xlsx");//todo 此处简单的使用了一下,百度有各种各样的工具类EasyExcel.read(file, User.class, new TestListener()).sheet().doRead();}
}

打印的日志如下:
在这里插入图片描述


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章