原创 一安 一安未来 2022-08-12 08:41 发表于北京
收录于合集#干货分享集78个
大家好,我是一安,今天聊一下日常开发经常用到的文件导入导出功能,本篇采用阿里巴巴开源EasyExcel实现
EasyExcel是阿里巴巴开源的一个excel处理框架,以使用简单、节省内存著称。
EasyExcel采用一行一行的解析模式,从磁盘上一行行读取数据,逐个解析,并将一行的解析结果以观察者的模式通知处理(AnalysisEventListener)。
github地址: https://github.com/alibaba/easyexcel
官方文档: https://easyexcel.opensource.alibaba.com/
引入easyexcel,为了简便代码,一并引入了lombok
com.alibaba
fastjson
1.2.83
org.projectlombok
lombok
1.18.6
com.alibaba
easyexcel
3.0.5
注意:方便测试,暂未使用spring管理,统一用main方法测试验证
文件监听器:
package com.capitek.excel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.util.ListUtils;
import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.Map;
/**
有个很重要的点 ReadExcelListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
*/
public class ReadExcelListener extends AnalysisEventListener
持久层:
package com.capitek.excel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.Map;
/**
* 这个类让spring管理,小编偷个懒未使用。
**/
public class DemoDAO {
private static final Logger LOGGER = LoggerFactory.getLogger(DemoDAO.class);
public void save(List> cachedDataList) {
LOGGER.info("入库条数:"+cachedDataList.size());
}
}
测试验证:
注意:读的时候可以通过设置excelType(ExcelTypeEnum.XLSX)指定写入文件类型,在easyexcel 3.0以后支持写入csv
package com.capitek.excel;
import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.util.IoUtils;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class TestReadMain {
/**
* @param stream excel文件流
* @param parseRowNumber 指定读取行
*/
public static void parseExcelToView(byte[] stream, Integer parseRowNumber) {
DemoDAO demoDAO = new DemoDAO();
ReadExcelListener readListener = new ReadExcelListener(demoDAO);
EasyExcelFactory.read(new ByteArrayInputStream(stream)).excelType(ExcelTypeEnum.XLSX).registerReadListener(readListener).headRowNumber(parseRowNumber).sheet(0).doRead();
}
/**
* 文件导入测试
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
FileInputStream inputStream = new FileInputStream(new File("easyexcel-export-user.xlsx"));
byte[] stream = IoUtils.toByteArray(inputStream);
parseExcelToView(stream, 2);
inputStream.close();
}
}
日志输出:
16:25:05.492 [main] INFO com.capitek.excel.ReadExcelListener - 解析到一条头数据:{0:"班级",1:"学生信息",2:"学生信息"}
16:25:05.496 [main] INFO com.capitek.excel.ReadExcelListener - 解析到一条头数据:{0:"班级",1:"姓名",2:"性别"}
16:25:05.506 [main] INFO com.capitek.excel.ReadExcelListener - 解析到一条数据:{0:"一年级",1:"张三0",2:"男"}
16:25:05.507 [main] INFO com.capitek.excel.ReadExcelListener - 解析到一条数据:{0:"一年级",1:"张三1",2:"男"}
16:25:05.513 [main] INFO com.capitek.excel.ReadExcelListener - 解析到一条数据:{0:"一年级",1:"张三2",2:"男"}
16:25:05.514 [main] INFO com.capitek.excel.ReadExcelListener - 解析到一条数据:{0:"一年级",1:"张三3",2:"男"}
16:25:05.515 [main] INFO com.capitek.excel.ReadExcelListener - 解析到一条数据:{0:"一年级",1:"张三4",2:"男"}
16:25:05.516 [main] INFO com.capitek.excel.ReadExcelListener - 5条数据,开始存储数据库!
16:25:05.516 [main] INFO com.capitek.excel.DemoDAO - 入库条数:5
16:25:05.516 [main] INFO com.capitek.excel.ReadExcelListener - 存储数据库成功!
16:25:05.516 [main] INFO com.capitek.excel.ReadExcelListener - 所有数据解析完成!
注意:写的时候可以通过设置excelType(ExcelTypeEnum.XLSX)指定写入文件类型,在easyexcel 3.0以后支持写入csv
package com.capitek.excel;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.alibaba.fastjson.JSONArray;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;
public class TestWriteMain {
private static final Logger LOGGER = LoggerFactory.getLogger(TestWriteMain.class);
/**
* 动态导出文件(通过map方式计算)
* @param headColumnMap 有序列头部
* @param dataList 数据体
* @return
*/
public static byte[] exportExcelFile(LinkedHashMap headColumnMap, List> dataList){
//获取列名称
List> excelHead = new ArrayList<>();
if(MapUtils.isNotEmpty(headColumnMap)){
//key为匹配符,value为列名,如果多级列名用逗号隔开
headColumnMap.entrySet().forEach(entry -> {
excelHead.add(CollectionUtil.newArrayList(entry.getValue().split(",")));
});
}
List> excelRows = new ArrayList<>();
if(MapUtils.isNotEmpty(headColumnMap) && CollectionUtils.isNotEmpty(dataList)){
for (Map dataMap : dataList) {
List
文件内容:
如果这篇文章对你有所帮助,或者有所启发的话,帮忙点赞、在看、转发、收藏,你的支持就是我坚持下去的最大动力!
一安未来
致力于Java,大数据;心得交流,技术分享;
71篇原创内容
公众号
一文让你了解cookie、session、token、OAuth2
多线程之间的通信方式你能说出几种
Nginx 面试 40 连问:上篇
Nginx 面试 40 连问:下篇
盲目用多线程反而容易导致 OOM
SpringBoot 实现大文件上传下载、分片、断点续传