背景
在当前的项目中,有一个需求是数据集文件的预览操作,既然是数据集,大数据量Excel文件也是不可避免的,几百列几万行数据那都是很正常的,因此需要做一个限定行列的都区方案。
因为只读前几行前几列,资源占用和读取时长都很短,因此想要直接同步读进行处理,但是EsayExcel同步读的时候,除了自己重写一些类之外,是默认注册了同步读监听器的,因此之前考虑用同步读一直没实现。
后来在Github下给作者大佬发了个ISSUES,JiaJu Zhuang 大佬给出提示,抛出ExcelAnalysisStopException异常,因此顺着这个思路来搞一下。
实现
监听器
因为同步读存在的制约,因此还是使用异步读,首先定义一个监听器类,实现异步读时的行列限制,这里定义LimitExcelReadListener并继承AnalysisEventListener;
因为我做的是数据集预览,行列均不固定,只能使用Map来接收行,代码不复杂,我直接给出完整代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| public class LimitExcelReadListener extends AnalysisEventListener<Map<Integer, String>> { private Integer limitColSize; private Integer limitRowSize; private List<Map<Integer, String>> headList = new ArrayList<>(); private List<Map<Integer, String>> dataList = new ArrayList<>(); LimitExcelReadListener() {
} LimitExcelReadListener(Integer limitColSize, Integer limitRowSize) { this.limitColSize = limitColSize; this.limitRowSize = limitRowSize; }
private Map<Integer, String> getLimitColMap(Map<Integer, String> oldMap) { Integer size = oldMap.keySet().size(); Map<Integer, String> newMap = new HashMap<>(); for (int i = 0; i < (size >= this.limitColSize ? this.limitColSize : size); i++) { newMap.put(i, oldMap.get(i)); } return newMap; }
@Override public void invoke(Map<Integer, String> integerStringMap, AnalysisContext analysisContext) { Map<Integer, String> newMap = this.getLimitColMap(integerStringMap); dataList.add(newMap); if (dataList.size() >= this.limitRowSize) { throw new ExcelAnalysisException(this.limitRowSize + "行" + this.limitColSize + "列读取完成"); } }
@Override public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) { Map<Integer, String> newMap = this.getLimitColMap(headMap); headList.add(newMap); }
@Override public void doAfterAllAnalysed(AnalysisContext analysisContext) { }
}
|
读取工具类
接着是读取的工具类,代码也很简单,这里直接贴出来:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| public class EExcelPrevUtils {
public static Map<String, Object> readLimitExcel(String path, Integer limitColSize, Integer limitRowSize) throws Exception { Map<String, Object> result = new HashMap<>(); FileInputStream inputStream = new FileInputStream(new File(path)); LimitExcelReadListener dataListener = new LimitExcelReadListener(limitColSize, limitRowSize); try { EasyExcel.read(inputStream, dataListener).sheet().doRead(); } catch (ExcelAnalysisException a) { System.out.println("读取完成"); result.put("headList", dataListener.getHeadList()); result.put("dataList", dataListener.getDataList()); } catch (Exception a) { System.out.println("读取失败"); throw a; } return result; } }
|
其他说明
以上代码都是基于一个Sheet的前提下做的,如果是多个sheet,就根据自己的需求重新搞下读取工具类即可
鸣谢
Alibaba EasyExcel
JiaJu Zhuang