最近接到一个Excel文件导入MySQL数据库的需求,查看了提供的导入模板,发现存在多个sheet页的情况;设想导入的Excel文件比较大,所以要考虑性能问题,推荐使用开源的工具,如阿里的easyExcel等,自己手写的话可能性能不佳。
注意inputStream流不能重复读取的问题。开发中我们肯定会对上传的文件进行必要的校验,所以文件会在内存中驻留一段时间,如果高并发的情况下可能导致内存瓶颈。
之前有尝试先存入本地磁盘上,然后分次读取不同的sheet页数据。如果文件不太大且机器内存足够的话把inputStream流转换为byte[]其实跟存入本地磁盘是一样的。
网上有推荐自定义inputStream流的,就是每次读取之后让指针回到开始位置达到重复读取。而我最后采用了转换字节数组的方法。Excel的读取用的Hutool的ExcelUtil工具类。
开发中发现,ExcelUtil不提供一次读取全部的sheet页,需要多次分别指定名称或类似下标的方式读取,默认读取第一个sheet。
还有就是,如果要实现每一个行的错误数据的提示,需要重写ExcelReader类的read方法。
@Override
public List<Map<String, Object>> read(int headerRowIndex, int startRowIndex, int endRowIndex) {
MapSheetReader reader = new MapSheetReader(headerRowIndex, startRowIndex, endRowIndex);
reader.setCellEditor(this.cellEditor);
reader.setIgnoreEmptyRow(this.ignoreEmptyRow);
reader.setHeaderAlias(this.headerAlias);
return (List)this.read((SheetReader)reader);
}
其中ignoreEmptyRow表示忽略行号,恰好这个行号是我想要的。而read方法的默认实现是忽略,查看如下构造方法。
public ExcelReader(Sheet sheet) {
super(sheet);
this.ignoreEmptyRow = true;
this.headerAlias = new HashMap();
}
重写该构造方法并设置this.ignoreEmptyRow = false即可。
另外ExcelUtil当中也提供了很多适用的方法,比如sheet页的个数、名称、是否Excel等用于校验模板是否正确。