POI和EasyExcel比较
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POI和EasyExcel比较相关的知识,希望对你有一定的参考价值。
参考技术A 1.userModel模式一种是使用最多的,像用的HSSFWorkBook、XSSFWorkBook、SXSSFWorkBook,这里我们称它为(也是内存消耗较大的模式)。为什么内存占用大呢?直接看读取源码,拿XSSFWorkbook加载为例,最终会调用这个方法:
这里就可以看到,会一直读流,每行都会生成一个对象,加载到zipEntries中去,这就是内存占用大的根本原因。
2.eventModel模式
也就是SAX模式,easyexcel就是重写了poi的这个方法,达到更小的内存占用。通过将流一行行的读取,加载到内存,达到节约内存的目的。
XlsxSaxAnalyser将数据读取成inputStream流,缓存到了sheetMap
拿到一行数据后,会去调用dealData方法,dealData方法会去调用之初始化的监听器,执行业务处理,readListener.invoke方法。
easyexcel快速入门
一 前言
本篇是EasyExcel快速入门知识,讲解如何读取,写入excel ,并给出了简单web示例;为什么要使用easyexcel;原因是相比于poi,easyexcel更加轻量级,读取写入API方便,并且在工作中占用内存较小;
官方描述如下:
Java解析、生成Excel比较有名的框架有Apache poi、jxl。但他们都存在一个严重的问题就是非常的耗内存,poi有一套SAX模式的API可以一定程度的解决一些内存溢出的问题,但POI还是有一些缺陷,比如07版Excel解压缩以及解压后存储都是在内存中完成的,内存消耗依然很大。easyexcel重写了poi对07版Excel的解析,能够原本一个3M的excel用POI sax依然需要100M左右内存降低到几M,并且再大的excel不会出现内存溢出,03版依赖POI的sax模式。在上层做了模型转换的封装,让使用者更加简单方便
知识追寻者(Inheriting the spirit of open source, Spreading technology knowledge;)
二 读取excel
读取的大体流程如下
- 读取数据流
- 将数据流映射到listener
- listener中处理读取的每条记录
- 读取完毕,进行清理;
2.1 读取
读取的方法如下,本方法是基于模型映射方法读取,其它方法请读者自行参考官方文档;
模型是User.class;
listener是UserDataListener
读取 第一个sheet;
@Test
public void testRead1(){
InputStream inputStream = null;
try {
// 获取输入流
inputStream = new FileInputStream("C:\mydata\generator\zszxz.xlsx");
// 解析每行结果在listener中处理
AnalysisEventListener listener = new UserDataListener();
// 读取excel
ExcelReader excelReader = EasyExcel.read(inputStream, User.class, listener)
.build();
// 读取sheet0
ReadSheet readSheet = EasyExcel.readSheet(0).build();
// 将 sheet 写入 Reader
excelReader.read(readSheet);
} catch (Exception e) {
} finally {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.2 模型实例
如下所示,index 参数代表excel对应的列,0表示第一列; value表示列对应的名称,在写入excel时作用较大;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
// id
@ExcelProperty(index = 0,value = "编号")
private Long id;
// 名称
@ExcelProperty(index = 1,value = "名称")
private String name;
// 创建时间
@ExcelProperty(index = 2,value = "创建时间")
private String createTime;
// 描述
@ExcelProperty(index = 3,value = "描述")
private String description;
}
2.3 AnalysisEventListener
实现 AnalysisEventListener接口;
invoke方法用于处理每条数据,读者可以在这边进行业务逻辑处理
doAfterAllAnalysed方法是只处理完所有数据后进行的动作;
@Component
public class UserDataListener extends AnalysisEventListener<User> {
// 用于存储读取到的数据
private List<User> datas = new ArrayList<User>();
// 这边你可以注入servie,或者mapper 进行业务逻辑处理后数据入库
/* *
* @Author lsc
* <p>解析每条数据处理的动作 </p>
* @Param [user, analysisContext]
* @Return void
*/
@Override
public void invoke(User user, AnalysisContext analysisContext) {
datas.add(user);
// do something
}
/* *
* @Author lsc
* <p> 解析所有数据之后处理的动作 </p>
* @Param [analysisContext]
* @Return void
*/
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
// 打印
System.out.println(datas);
// do something
// 清理
datas.clear();
}
}
三 写入excel
3.1 准备的数据
准备的数据也是一个List集合,存储读取的每行数据;
public class DataUtils {
public static List<User> getUserData(){
// 写入响应
List<User> datas = new ArrayList<User>();
User user = new User();
user.setId(666L);
user.setName("知识追寻者");
user.setCreateTime(LocalDateTime.now().toString());
user.setDescription("跟着知识追寻者学习吧");
datas.add(user);
return datas;
}
}
3.2 写入
写入的数据更加简单,因为有了之前的模型映射;
@Test
public void simpleWrite() {
// 文件名
String fileName = "C:\mydata\generator\知识追寻者.xlsx";
// 写入
EasyExcel.write(fileName, User.class).sheet("知识追寻者").doWrite(DataUtils.getUserData());
}
四 web上传下载示例
@RestController
public class ExcelController {
@GetMapping("download")
public void download(HttpServletResponse response) throws IOException {
// 设置 ContentType
response.setContentType("application/vnd.ms-excel");
// 设置字符集
response.setCharacterEncoding("utf-8");
// 防止中文乱码
String fileName = URLEncoder.encode("知识追寻者", "UTF-8");
// 设置 header
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
// 写入
EasyExcel.write(response.getOutputStream(), User.class)
.sheet("知识追寻者")// 指定sheet名称
.doWrite(DataUtils.getUserData());//写入数据
}
@PostMapping("upload")
@ResponseBody
public String upload(MultipartFile file) throws IOException {
EasyExcel.read(file.getInputStream(), User.class, new UserDataListener())
.sheet()
.doRead();
return "success";
}
}
五参考链接
https://github.com/alibaba/easyexcel
以上是关于POI和EasyExcel比较的主要内容,如果未能解决你的问题,请参考以下文章
poi和easyExcel基于Java操作Excel学习笔记