使用Hutool的流方式读取Excel大文件
官网介绍: 在标准的ExcelReader中,如果数据量较大,读取Excel会非常缓慢,并有可能造成内存溢出。因此针对大数据量的Excel,Hutool封装了Sax模式的读取方式。 Excel07SaxReader支持Excel2007格式的Sax读取。
参考他人博客结合使用经验,总结如下工具类ExcelKit: (类完整代码如下)
package com.xxx.app.blog.common.kit; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.copier.CopyOptions; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Console; import cn.hutool.core.util.ReflectUtil; import cn.hutool.poi.excel.sax.Excel07SaxReader; import cn.hutool.poi.excel.sax.handler.RowHandler; import java.util.*; /** * ExcelKit excel文件处理库,依赖Hutool */ public class ExcelKit { private static List<Object> headLine; private static List<Map<String, Object>> datas = new ArrayList<>(); /** * @param pathAndName 文件路径 * @param idOrRidOrSheetName Excel中的sheet id或者rid编号或sheet名称,rid必须加rId前缀,例如rId1,如果为-1处理所有编号的sheet */ public static List<Map<String, Object>> readBigExcel(String pathAndName, int idOrRidOrSheetName) { Console.log("【{}】 开始读取 ... ", pathAndName); datas.clear(); Excel07SaxReader reader = new Excel07SaxReader(new MyRowHandler()); reader.read(pathAndName, idOrRidOrSheetName); Console.log("【{}】 读取完成 ... ", pathAndName); return datas; } /** * @param pathAndName 文件路径 * @param idOrRidOrSheetName Excel中的sheet id或者rid编号或sheet名称,rid必须加rId前缀,例如rId1,如果为-1处理所有编号的sheet * @param beanType 类类型 * @param <T> 返回值为List<T> * @return */ public static <T> List<T> read(String pathAndName, int idOrRidOrSheetName, Class<T> beanType) { return read(pathAndName, idOrRidOrSheetName, beanType, Collections.EMPTY_MAP); } /** * @param pathAndName 文件路径 * @param idOrRidOrSheetName Excel中的sheet id或者rid编号或sheet名称,rid必须加rId前缀,例如rId1,如果为-1处理所有编号的sheet * @param beanType 类类型 * @param fieldMapping T类型对应的别名,即类类型对应的 excel 的关系 * @param <T> 返回值为List<T> * @return */ public static <T> List<T> read(String pathAndName, int idOrRidOrSheetName, Class<T> beanType, Map<String, String> fieldMapping) { CopyOptions copyOptions = CopyOptions.create(); if (CollUtil.isNotEmpty(fieldMapping)) { copyOptions.setFieldMapping(fieldMapping); } readBigExcel(pathAndName, idOrRidOrSheetName); List<T> datalist = new ArrayList<>(); for (Map<String, Object> data : datas) { T t = ReflectUtil.newInstanceIfPossible(beanType); datalist.add(BeanUtil.fillBeanWithMap(data, t, copyOptions)); } return datalist; } private static class MyRowHandler implements RowHandler { @Override public void handle(int sheetIndex, long rowIndex, List<Object> rowList) { //Console.log("[{}] [{}] {}", sheetIndex, rowIndex, rowList); if (rowIndex == 0) { headLine = rowList; } else { Map<String, Object> tMap = new HashMap<>(rowList.size()); for (int i = 0; i < rowList.size(); i++) { tMap.put(transStr(headLine.get(i)), rowList.get(i)); } datas.add(tMap); } } } private static String transStr(Object obj) { return obj == null ? "" : obj.toString(); } }
调取使用方法:
//大数据量excel读取方式 List<Map<String,Object>> recordBMapList = null; recordBMapList = ExcelKit.readBigExcel("文件路径",-1); //第二个参数,-1代表读取全部sheet数据;0代表读取第一个sheet数据,依次类推;
上一篇:
通过多线程提高代码的执行效率例子