ITPub博客

首页 > 应用开发 > Java > POI 分批读取Excel数据

POI 分批读取Excel数据

Java 作者:xz43 时间:2022-05-17 10:41:53 0 删除 编辑

我们在读取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格式;

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/9399028/viewspace-2894802/ ,如需转载,请注明出处,否则将追究法律责任。

下一篇: Swagger Edit介绍
请登录后发表评论 登录
全部评论
鱼儿的学习空间

注册时间:2010-11-16

  • 博文量
    433
  • 访问量
    1863719