前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用EasyExce实现Excel文件解析

使用EasyExce实现Excel文件解析

作者头像
灰小猿
发布2022-11-02 18:09:03
2K0
发布2022-11-02 18:09:03
举报
文章被收录于专栏:灰小猿技术社区

hello,你好呀,我是灰小猿,一个超会写bug的程序猿!

在上一篇文章中我和大家简单的介绍了使用easyexcel技术在有对象和无对象情况下实现Excel文件的写入操作,

那么今天这一篇文章,我就继续来和大家讲一下,使用easyexcel技术如何读取excel中的数据呢?

easyexcel的优势

在Java领域解析、生成Excel比较有名的框架有Apache poi,jxl等,但是在使用的时候,其实他们都存在一个严重的问题,就是非常的耗内存,如果你的系统并发量不大的话,可能还行,但是一旦并发上来后一定会OOM或者JVM频繁的垃圾回收.

而EasyExcel是阿里巴巴开源的一个excel处理框架,他具有使用简单,节省内存的特点,EasyExcel能大大减少占用内存的主要原因是在解析Excel时没有将文件数据一次性全部加载到内存中,而是从磁盘上一行行读取数据,逐个解析的,这一特点待会在读取excel数据的时候也会体现出来。

添加easyexcel依赖

使用easyexcel时需要在pom中导入相应的依赖文件,

代码语言:javascript
复制
        <!--poi依赖03版本-->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.17</version>
        </dependency>
        <!--poi依赖07版本-->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.17</version>
        </dependency>
        <!--easyexcel依赖-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>2.2.6</version>
        </dependency>

由于easyexcel是在poi的基础上发展起来的,所以在导入依赖的时候,也需要导入对03和07版本的excel的依赖。

使用easyexcel读取数据

在使用easyexcel读取文件数据的时候,需要设置一个监听器,通过实现该监听器,就可以实现数据的单行读取操作, 我们以下面的这个数据对象为例:

代码语言:javascript
复制
/**
 * 基本数据demodata
 */
@Data
public class DemoData {
    @ExcelProperty(value = "字符串标题")
    private String stringTitle;
    @ExcelProperty(value = "时间标题")
    private Date dateTitle;
    @ColumnWidth(50)
    @ExcelProperty(value = "数字标题")
    private int doubleTitle;
}

读取的数据内容如下:

监听器的实现

在读取excel数据的时候,需要实现AnalysisEventListener监听器,其中需要传入对应的数据类型,在该监听接口中,主要使用的方法是:

  • invoke:一行一行读取,每读取一行数据时就会调用该方法。
  • invokeHeadMap:读取表头数据,
  • doAfterAllAnalysed:所有数据读取完毕之后调用,一般用于对最后读取到的数据进行处理。
  • onException:在转换异常,获取其他异常的情况下会调用此接口,抛出异常就停止读取,如果不抛出异常就继续读取

接口的实现如下:

代码语言:javascript
复制
/**
 * 读取excel,设置监听器
 */
@Slf4j
public class DemoDataListener extends AnalysisEventListener<DemoData> {

    /**
     * 定义一个存储的界限,每读取5条数据就存储一次数据库,防止数据过多时发生溢出
     * 存储完成之后就清空list重新读取新的数据,方便内存回收
     */
    private static final int BATCH_COUNT = 5;

    /**
     * 定义一个数据存储缓存,用于临时存储读取到的数据
     */
    private List<DemoData> cacheDataList = new ArrayList<>();


    //    对接持久层的dao
    private DemoDao demoDao;

    /**
     * 无参构造
     */
    public DemoDataListener() {
//        由于是示例,所以这里直接new一个dao
        this.demoDao = new DemoDao();
    }

    /**
     * 有参构造,如果无法直接Autowired,那么需要在有参构造中传入
     *
     * @param demoDao
     */
    public DemoDataListener(DemoDao demoDao) {
        this.demoDao = demoDao;
    }

    /**
     * 一行一行读取
     *
     * @param demoData
     * @param analysisContext
     */
    @Override
    public void invoke(DemoData demoData, AnalysisContext analysisContext) {
        log.info("读取到数据:" + demoData);
        cacheDataList.add(demoData);
        /**
         * 如果当前缓存列表中的数据等于指定值,就存储
         */
        if (cacheDataList.size() == BATCH_COUNT) {
            //保存数据到数据库
            saveData();
            //清空缓存列表重新读取
            cacheDataList.clear();
        }

    }

    @Override
    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
        log.info("表头:" + headMap);
    }

    /**
     * 读取结束后
     *
     * @param analysisContext
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        log.info("读取结束~~~");
//        将最后的数据存储到数据库
        saveData();
        cacheDataList.clear();
    }

    /**
     * 在转换异常,获取其他异常的情况下会调用此接口,
     * 抛出异常就停止读取,如果不抛出异常就继续读取。
     * @param exception
     * @param context
     * @throws Exception
     */
    @Override
    public void onException(Exception exception, AnalysisContext context) throws Exception {
        log.info("解析失败,但是继续解析下一行:{}",exception.getMessage());

        if (exception instanceof ExcelDataConvertException){
            ExcelDataConvertException e = (ExcelDataConvertException) exception;
            log.info("数据解析异常,所在行:{},所在列:{},数据是:{}",e.getRowIndex(),e.getColumnIndex(),e.getCellData());
        }
    }

    /**
     * 将数据存储到持久层
     */
    private void saveData() {
        log.info("将要保存【" + cacheDataList.size() + "】条数据入库");
        demoDao.saveDataforList(cacheDataList);
        log.info("【" + cacheDataList.size() + "】条数据入库成功!");
    }


}

接口实现完毕之后,进行数据读取的方法其实是非常简单,只需要一句代码就可以了,

读取如下:

代码语言:javascript
复制
    /**
     * 从excel中读取全部工作表的数据
     */
    public void readAllSheetDataForExcel() {
        /**
         * 主要是doReadAll()方法
         */
        EasyExcel.read(FILEPATH + "testExcel_1.xlsx", DemoData.class, new DemoDataListener()).sheet().doRead();
    }

读取结果如下:

以上就是使用easyexcel技术读取数据的操作, 之后会继续和大家分享读取和写入复杂数据。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-10-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • easyexcel的优势
  • 添加easyexcel依赖
  • 使用easyexcel读取数据
    • 监听器的实现
    相关产品与服务
    数据保险箱
    数据保险箱(Cloud Data Coffer Service,CDCS)为您提供更高安全系数的企业核心数据存储服务。您可以通过自定义过期天数的方法删除数据,避免误删带来的损害,还可以将数据跨地域存储,防止一些不可抗因素导致的数据丢失。数据保险箱支持通过控制台、API 等多样化方式快速简单接入,实现海量数据的存储管理。您可以使用数据保险箱对文件数据进行上传、下载,最终实现数据的安全存储和提取。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档