easyexcel导入时读不到数据_easyexcel读取任意表格以及使用中的坑

关于easyexcel通过模板读取表格的,网上已经有好多了,而且源码里也有详细的demo,这里就不在多说。这里记录一下我的使用。

一:

目前有个接口是上传Excel并且返回第一行,之前用的是POI,但是数据量大的话,100w条数据就oom了,所以切换到easyexcel,之后内存占用果然小了许多。

二:

首先引入依赖,目前我用的是2.1.4

com.alibaba

easyexcel

2.1.4

然后创建一个listener,这个需要继承AnalysisEventListener,

import com.alibaba.excel.context.AnalysisContext;

import com.alibaba.excel.event.AnalysisEventListener;

import com.alibaba.excel.exception.ExcelDataConvertException;

import com.ehl.etl.ext.utils.JSONArray;

import com.ehl.etl.ext.utils.JSONObject;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import java.util.Map;

public class ExcelReadListener extends AnalysisEventListener> {

private Logger logger = LoggerFactory.getLogger(ExcelReadListener.class);

每隔N条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收

private static final int BATCH_COUNT = 3000;

//自定义用于暂时存储数据,通过Getter在方法中获取

JSONArray array = new JSONArray();

/**

* 在转换异常 获取其他异常下会调用本接口。抛出异常则停止读取。如果这里不抛出异常则 继续读取下一行。

* 如果不重写该方法,默认抛出异常,停止读取

*

* @param exception

* @param context

* @throws Exception

*/

@Override

public void onException(Exception exception, AnalysisContext context) {

logger.error("解析失败,但是继续解析下一行:{}", exception.getMessage());

if (exception instanceof ExcelDataConvertException) {

ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException)exception;

logger.error("第{}行,第{}列解析异常,数据为:{}", excelDataConvertException.getRowIndex(),

excelDataConvertException.getColumnIndex(), excelDataConvertException.getCellData());

}

}

/**

* 每解析一行会回调invoke()方法。

* 如果当前行无数据,该方法不会执行,

* 也就是说如果导入的的excel表无数据,该方法不会执行,

* 不需要对上传的Excel表进行数据非空判断

*

* @param map 当前读取到的行数据

* @param analysisContext 定义了获取读取excel相关属性的方法

*/

@Override

public void invoke(Mapmap, AnalysisContext analysisContext) {

//目前只需要表格第一行,这里直接跳过

return;

}

/**

* 这里会一行行的返回头,每个sheet只返回一次

*

* @param headMap

* @param context

*/

@Override

public void invokeHeadMap(MapheadMap, AnalysisContext context) {

logger.info("解析到一条头数据:{}", headMap.toString());

for (int i = 0; i < headMap.size(); i++) {

JSONObject object = new JSONObject();

object.put("name","c_"+(i+1));

object.put("type","String");

if (headMap.get(i) == null) {

object.put("desc","");

} else {

object.put("desc",headMap.get(i));

}

array.add(object);

}

}

/**

* 解析监听器

* 每个sheet解析结束会执行该方法

*/

@Override

public void doAfterAllAnalysed(AnalysisContext analysisContext) {

logger.info("/*------- 当前sheet读取完毕-------*/");

//如果要在方法中拿到值,这里就不能清除,

//array.clear();

}

public JSONArray getArray() {

return array;

}

public void setArray(JSONArray array) {

this.array = array;

}

}

然后就是我们的主类了

InputStream inputStream = file.getInputStream();

BufferedInputStream bufferedInputStream = new BufferedInputStream(file.getInputStream());

ExcelReadListener listener = new ExcelReadListener();

ExcelReader excelReader = EasyExcelFactory.read(inputStream, listener).build();

// 直接读取第一个sheet,从0开始

ReadSheet readSheet = EasyExcel.readSheet(0).build();

excelReader.read(readSheet);

// 可以通过getter获取到listener中暂存的值,

JSONArray data = listener.getArray();

// 这里千万别忘记关闭,读的时候会创建临时文件,到时磁盘会崩的

excelReader.finish();

这样就不需要建立模板直接获取内容了。

有一点要注意:

这里默认是1,就是0行为头,从第一行开始读取内容,如果将这里指定为0的话,invokeHeadMap就拿不到值了。

三:

执行顺序是先执行invokeHeadMap然后是invoke遍历每一行,最后执行doAfterAllAnalysed结束,这里特别注意,如果在doAfterAllAnalysed中清除了暂存的值,那么在主函数中是拿不到的。

四:

如果在使用easyexcel时遇到这种问题,就是和POI的依赖冲突了。目前所知的2.1.4版本无法和3.14的POI一起存在,3.17版POI则没有冲突

关于这个工具我只是大概了解了一下,这个invoke方法如果有值的话每行都会调用它,那么如果我想只获取一行,但是数据量又特别大的时候,就会调用好多次invoke,造成效率低下。如果有人有好的方法欢迎留言。

你可能感兴趣的:(easyexcel导入时读不到数据_easyexcel读取任意表格以及使用中的坑)