Java大批量Excel读取解决方案

本文介绍了一种有效的大数据量Excel读取方案,通过使用特定依赖和分段缓存技术,避免了内存溢出问题,适用于处理超过15万行的大文件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们在读取excel过程中,通常使用的方案为POI的普通读取,但是遇到大数据量excel (比如一个excel超过20M,上10万行上百列等),此时一般代码会报内存溢出(OOM);

以下为一种解决方案(亲测有效):

首先引入的依赖:

 <!--大批量excel导入依赖开始-->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>4.0.0</version>
        </dependency>

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-scratchpad</artifactId>
            <version>4.0.0</version>
        </dependency>

        <!-- 读取大量excel数据时使用 -->
        <dependency>
            <groupId>com.monitorjbl</groupId>
            <artifactId>xlsx-streamer</artifactId>
            <version>2.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>4.0.0</version>
        </dependency>
        <!--大批量excel导入依赖结束-->

Java代码:

  /**
     * 大批量数据读取 15W以上
     * 思路:采用分段缓存,防止出现OOM的情况
     * 格式限制:必须使用xlsx的格式,调用前需判断格式
     */
    public static List<Map<String,Object>> readBigExcel(MultipartFile file,String rowname,int stasheetNum,int starowNum,int stacolumn)throws Exception{
        //定义返回值
        List<Map<String,Object>> resultList=new ArrayList<Map<String,Object>>();
        InputStream inputStream=file.getInputStream();
       try( Workbook wk= StreamingReader.builder()
                .rowCacheSize(100)  //缓存到内存中的行数,默认是10
                .bufferSize(4096)  //读取资源时,缓存到内存的字节大小,默认是1024
                .open(inputStream); ){ //打开资源,必须,可以是InputStream或者是File,注意:只能打开XLSX格式的文件
        Sheet sheet = wk.getSheetAt(stasheetNum);
        String[] rownameSplit=rowname.split(",");
        int columnlength=rownameSplit.length;
        Cell cell=null;//定义单元格
        //遍历所有的行()
        for (Row row :sheet) {
            //row=sheet.getRow(i);//获取当前循环的行数据(因为只缓存了部分数据,所以不能用getRow来获取)此处采用增强for循环直接获取row对象
            Map<String, Object> paramMap = new HashMap<String, Object>();//定义一个map做数据接收
            if (row.getRowNum() >= starowNum) { //从设定的行开始取值
                //System.out.println("开始遍历第" + row.getRowNum() + "行数据:");
                //对当前行逐列进行循环取值
                for (int j = stacolumn; j < columnlength; j++) {
					/**
					   注:MyUtil.isEmpty为工具类判空方法,可替换为自己的判空工具
					**/
                    if (MyUtil.isEmpty(row)) {
                        paramMap.put(rownameSplit[j], null);//将单元格值放入map
                    } else {
                        cell = row.getCell(j);//获取单元格数据
                        if (MyUtil.isEmpty(cell) && cell.getCellType() == CellType.BLANK) {
                            paramMap.put(rownameSplit[j], null);//将单元格值放入map
                        } else {
                            paramMap.put(rownameSplit[j], cell.getStringCellValue());//将单元格值放入map
                        }

                    }

                }
                //一行循环完成,将map存入list
                resultList.add(paramMap);
            }
        }


        }
        return resultList;
    }

参数解释:

file:前台页面传递的文件

rowname:为读取的每个列起的名字。如excel文件列为 姓名,身份证,性别 ;此处可传字符串"name,card,sex";

stasheetNum:读取的工作簿  从0开始

starowNum: 开始读取的行  从0开始

stacolumn:开始读取的列 从0开始

返回值:List<Map<String,Object>>  将读取的内容 封装为到一个list中,并以map形式存放;

可根据实际情况进行调整:

注:POI版本需4以上,excel只能读取xlsx格式;如有更好方案 欢迎留言分享

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值