篇首语:本文由小编为大家整理,主要介绍了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:mydatageneratorzszxz.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@AllArgsConstructorpublic 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方法是只处理完所有数据后进行的动作;
@Componentpublic class UserDataListener extends AnalysisEventListener { // 用于存储读取到的数据 private List datas = new ArrayList(); // 这边你可以注入servie,或者mapper 进行业务逻辑处理后数据入库 /* * * @Author lsc * 解析每条数据处理的动作
* @Param [user, analysisContext] * @Return void */ @Override public void invoke(User user, AnalysisContext analysisContext) { datas.add(user); // do something } /* * * @Author lsc * 解析所有数据之后处理的动作
* @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 getUserData(){ // 写入响应 List datas = new ArrayList(); 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:mydatagenerator知识追寻者.xlsx"; // 写入 EasyExcel.write(fileName, User.class).sheet("知识追寻者").doWrite(DataUtils.getUserData()); }
四 web上传下载示例
@RestControllerpublic 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比较的主要内容,如果未能解决你的问题,请参考以下文章