通过sax和流式写实现读写excel的内存占用优化

记一次excel处理优化

刚入职第一个需求

这是入职做的第一个需求,系统中有一个拼接excel的功能(第一个excel和第二个excel横向拼接成一个新的excel,再继续和下一个excel拼接成一个更大的excel)。通常处理excel会使用jxl或者poi,poi支持excel2007,jxl只支持到excel2003(即以.xls结尾的excel),所以我们选择使用poi来处理excel,但是poi有个很大的缺陷,常用的用户模式内存占用过高,一个3M的excel经过poi读取之后会占用600m甚至更大的内存,所以就有了这个需求:优化内存占用。

思路

poi官网上提供了三种读写excel的方式
在这里插入图片描述
eventmodel即sax模式,cpu和内存占用低,但是只能读,不能写。usermodel即将excel解析成dom的方式,这种方式是最常用的,但是cpu和内存占用很高。sxssf即流式写的方式,cpu和内存占用低,但是只能写,不能读。
看过这三种方式之后,很容易想到使用sax模式来读,使用流式写来写。

细节

首先是实现sax模式,sax模式除了依赖poi相关的包之外,还依赖xmlReader相关的包(xlsx格式的excel是通过xml来存储数据的,sax模式的本质是解析xml),导入包后,需要继承DefaultHandler,重写startElement,endElement,characters三个回调方法。startElement方法用于解析到xml的开标签的时候执行,endElement方法用于解析到闭标签的时候执行,characters用于获取标签中间的数据,也就是单元格中的数据。

    <!-- https://mvnrepository.com/artifact/xerces/xercesImpl -->
    <dependency>
        <groupId>xerces</groupId>
        <artifactId>xercesImpl</artifactId>
        <version>2.12.0</version>
    </dependency>

        private static class ExcelDataHandler extends DefaultHandler {
   
        private SharedStringsTable sst;
        private List<List<Object>> data;
        private List<Object> currentRow;
        private Object lastContent;
        private int lastRow;
        private int lastCol;
        private boolean sstRef; // 是否是sst的索引
        private boolean numValue; // 是否是数字

        public ExcelDataHandler(SharedStringsTable sst) {
   
            this.sst = sst;
            this.data = new ArrayList<>();
            lastCol = lastRow = -1;
        }

        public List<List<Object>> getData(</
  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值