阿里出的EasyExcel,基于java,省内存的读写Excel的开源项目,支持读写百M大小的Excel。
读:定义实体类接受表字段,加注解,写监听类,继承一个Listense类,重写里面的方法。要注意监听类不能被spring管理,所以每次需要new。
其中一个方法是一行一行读取数据,封装到对象中,可以重写这个方法实现,自己定义逻辑。建议如果要读取表格直接封装到数据库的话,可以每读取100条然后调用一次存储,否则几万条数据在内存可能会导致OOM内存溢出。
还有一个方法是读取表头
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.1.6</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.17</version>
</dependency>
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.xxx.dao.BaseDao;
import java.util.ArrayList;
import java.util.List;
public class ExcetListener<T> extends AnalysisEventListener<T> {
//每读取100条存储一次数据库,然后清理list ,方便内存回收
private static final int BATCH_COUNT = 100;
List<T> addList = new ArrayList<>();
/**
* 每一条数据解析都会来调用该方法
*
* @param t 对应实体类
* @param analysisContext analysisContext
*/
@Override
public void invoke(T t, AnalysisContext analysisContext) {
addList.add(t);
if (addList.size() >= BATCH_COUNT) {
saveData();
addList.clear();
}
}
/*
* 所有数据解析完成了 会调用该方法
*
* @param analysisContext
*/
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
//。。
}
/*
* 加上存储数据库
*/
private void saveData() {
if (addList.isEmpty()) {
return;
}
baseDao.insertBatch(addList, "dbName", "collectionName");
}
/**
* 读取表头的方法,会把表头读取到map中,key是位置索引,value是表头字段
*
* @param headMap
* @param context
*/
@Override
public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
//。。。
}
/**
* 读取到某一行数据异常时会进入的方法。可以打印日志定位异常的行,列。
*
* @param exception
* @param context
* @throws Exception
*/
@Override
public void onException(Exception exception, AnalysisContext context) throws Exception {
//。。。
}
EasyExcel.read(file,
Student.class,
new ExcetListener<>(new BaseDao<Student>()))
.sheet(0)
.doRead();
}
@Getter
@Setter
@EqualsAndHashCode
public class Student{
/**
* 强制读取第三个 这里不建议 index 和 name 同时用,要么一个对象只用index,要么一个对象只用name去匹配
*/
@ExcelProperty(index = 2)
private Double doubleData;
/**
* 用名字去匹配,这里需要注意,如果名字重复,会导致只有一个字段读取到数据
*/
@ExcelProperty("字符串标题")
private String string;
@ExcelProperty("日期标题")
private Date date;
}