hutool 支持excel导入 导出 底层使用的是依赖是需要导入poi
由于项目中excel导入的列名不是固定,所以只能使用行来读,不需要定义实体类,缺点就是只能读一个sheet,经过测试大文件会出现oom,由于之前使用的ExcelUtil.getReader不支持读取大文件。第二个坑就是excel文件格式 xlsx这个才是正确,xls读大文件会出现不兼容日期的现象。下面科普一下。
.xls,文件存储格式实现原理是基于微软的ole db是微软com组件的一种实现,本质上也是一个微型数据库,由于微软的东西很多不开源,基本上也已经被淘汰,了解它的细节意义不大。
.xlsx ,文件存储格式实现是基于openXml和zip技术((用winrar可以打开看)。它的优点是简单存储、安全传输方便、处理数据简单。
原因是:读取excel全部内容到内存中,当文件内容几十万条 很显然会造成Jvm内存溢出。
ExcelReader reader = ExcelUtil.getReader(file.getInputStream());
解决方式使用:hutool提供的api readBySax可以支持去大文件,这是poi做出的优化。
new RowHandler() 需要重写他的方法
注意:在此说明其实使用的是 org.apache.poi**,hutool在底层调用是poi
ExcelUtil.readBySax(file.getInputStream(), 0, new RowHandler() {
@Override
public void handle(int i, int i1, List<Object> list) {
//list 此时的内容就是 excel一行的内容,
//我理解是一行一行读 读完就释放,上面的方法是一口气读全部到内存
Console.log("[{}] [{}] {}", i, i1, list);
}
});
1、上代码 + pom 依赖
<!-- hutool 工具包 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>4.1.19</version>
</dependency>
<!-- poi exce表格导入导出 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
<!-- poi需要使用 excel表格解析器 -->
<dependency>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
<version>2.11.0</version>
</dependency>
代码
package com.excel.batch.excelBatchController;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.sax.handler.RowHandler;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.List;
import java.util.Map;
/**
* @Author: 宋忠瑾
* @Description: excel 导入实现 文件格式 xlsx
* @Date: Create in 17:14 2021/8/31
*/
@RestController
public class Test {
/**
* 仅限小文件读取
*/
@PostMapping("/excel1")
public void importOneExcel(@RequestParam(name = "file") MultipartFile file) throws IOException {
ExcelReader reader = ExcelUtil.getReader(file.getInputStream());
//1、读取Excel中所有行和列,都用列表表示 可以指定从哪行开始读 默认从0开始读
List<List<Object>> read = reader.read(1);
//2、读取为Map列表,默认第一行为标题行,Map中的key为标题,value为标题对应的单元格值。
List<Map<String,Object>> readAll = reader.readAll();
//3、读取为Bean列表,Bean中的字段名为标题,字段值为标题对应的单元格值。
List<Object> all = reader.readAll(Object.class);
System.out.println("read = " + read);
}
/**
* 支持大文件读取
* @Description excel表格批量 大文件
* @Method importExcel 导入excel
* @Author 宋忠瑾
* @Date 2021/8/31 17:36
* @param file excel
* @return void 无返回
*/
@PostMapping("/excel")
public void importBatchExcel(@RequestParam(name = "file") MultipartFile file) throws IOException {
ExcelUtil.readBySax(file.getInputStream(), 0, new RowHandler() {
@Override
public void handle(int i, int i1, List<Object> list) {
System.out.println(list);
}
});
}
}
测试