[alibaba/easyexcel]关于读取大文件时只读取前几行前几列的相关解决方案

2024-05-10 747 views
1

按照文档进行了读取,同步读取时,对于大文件总是全部行读取完毕后才返回结果,是否能够实现限制读取行数?例如十万行十万列的EXCEL文件,只读取前50行前50列的效果呢。

回答

8

抛出 ExcelAnalysisStopException 异常

9

谢谢大佬指点!

恬不知耻的加个引流外链请大佬别见怪,小弟会将拙见整理出来发布到:javafeng.com

读取前几行前几列我自己简单实现了一下,后面有人看到的话可以简单参考:

监听器,读取到指定数量行的时候,抛出ExcelAnalysisStopException异常,指定列的话直接取每行前几个Key即可:

package com.ainote.utils;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.exception.ExcelAnalysisException;
import com.alibaba.fastjson.JSON;
import lombok.Data;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Data
public class LimitExcelReadListener extends AnalysisEventListener<Map<Integer, String>> {
    /**
     * 表头数据
     */
    private List<Map<Integer, String>> headList = new ArrayList<>();
    /**
     * 数据体
     */
    private List<Map<Integer, String>> dataList = new ArrayList<>();

    @Override
    public void invoke(Map<Integer, String> integerStringMap, AnalysisContext analysisContext) {
        Map<Integer, String> newMap = this.getLimitColMap(integerStringMap,20);
        System.out.println(JSON.toJSONString(newMap));
        dataList.add(newMap);
        // 控制读取前几行,读取完之后抛出异常,读取时捕获此异常,捕获到异常时代表读取完毕
        if (dataList.size() >= 50) {
            throw new ExcelAnalysisException("50行20列读取完成");
        }
    }

    @Override
    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
        Map<Integer, String> newMap = this.getLimitColMap(headMap,20);
        System.out.println(JSON.toJSONString(newMap));
        headList.add(newMap);
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
    }
    // 因为我有读取前几列的需求,所以简单写了下取前几个列,不需要的只需要控制前几行即可
    private Map<Integer, String> getLimitColMap(Map<Integer, String> oldMap, Integer limit){
        Integer size = oldMap.keySet().size();
        Map<Integer, String> newMap = new HashMap<>();
        for (int i = 0; i < (size >= limit ? limit : size); i++) {
            newMap.put(i,oldMap.get(i));
        }
        return newMap;
    }
}

读取:

package com.ainote.utils;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.exception.ExcelAnalysisException;
import com.alibaba.fastjson.JSONArray;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.List;
import java.util.Map;

public class EExcelPrevUtils {
    public static void main(String[] args) throws FileNotFoundException {
        FileInputStream inputStream = new FileInputStream(new File("/Users/javafeng/Downloads/mobile-churn-data.xlsx"));
        //初始化一个监听器
        LimitExcelReadListener dataListener = new LimitExcelReadListener();
        //读取文件数据
        try {
            EasyExcel.read(inputStream, dataListener).sheet().doRead();
        } catch (ExcelAnalysisException a) {
            System.out.println("读取完成");
        }
    }
}
2

重写hasNext方法应该也可以

9

手动判断抛出异常,但是这种也比较慢,100mexcel数据,读取100行,5s左右。猜测瓶颈在于inputstream解析成对象这一过程。待验证~

3

@aboerrr 我这里实测40m的文件,读取前500行,时间为760ms,可联系blog@javafeng.com,我这有验证视频

8

重写hasNext方法应该也可以

清晰~

6

重写hasNext方法应该也可以

正解!