首页 > 其他分享 >如何解决excel导入大文件报错

如何解决excel导入大文件报错

时间:2023-12-20 11:04:34浏览次数:43  
标签:return excel value inputStream static 导入 报错 param dataClass

开发过程中我们经常会遇到Excel导入大文件报错的问题,经过不断 的摸索,我发现我们可以利用缓存区来实现大文件的上传,下面是我本人封装的一个实现工具,有兴趣的小伙伴可以看看,希望能对大家有所帮助!

public class ExcelImportBigDataUtil {


    /**
     * 每次放入缓冲区最大行数
     */
    private static final int MAX_ROW_NUM = 10000;

    /**
     * 缓冲区大小
     */
    private static final int BUFFER_SIZE = 4096;

    /**
     * 通过文件路径获取excel数据
     *
     * @param filePath  文件路径
     * @param dataClass 转换的对象
     */
    public static <E> List<E> importData(String filePath, Class<E> dataClass) {
        return importData(filePath, dataClass, false);
    }

    /**
     * 通过文件路径获取excel数据
     *
     * @param filePath  文件路径
     * @param dataClass 转换的对象
     */
    public static <E> List<E> importDataForMore(String filePath, Class<E> dataClass) {
        return importData(filePath, dataClass, true);
    }

    /**
     * 通过输入流获取excel数据
     *
     * @param inputStream 输入流
     * @param dataClass   转换的对象
     */
    public static <E> List<E> importData(InputStream inputStream, Class<E> dataClass) {
        return importData(inputStream, dataClass, false);
    }

    /**
     * 通过输入流获取excel数据
     *
     * @param inputStream 输入流
     * @param dataClass   转换的对象
     */
    public static <E> List<E> importDataForMore(InputStream inputStream, Class<E> dataClass) {
        return importData(inputStream, dataClass, true);
    }

    /**
     * 通过文件路径获取excel数据
     *
     * @param filePath  文件路径
     * @param dataClass 转换的对象
     * @param moreSheet 是否是多sheet页
     */
    private static <E> List<E> importData(String filePath, Class<E> dataClass, boolean moreSheet) {
        FileInputStream inputStream = null;
        try {
            if (VerifyUtil.nonNull(filePath)) {
                inputStream = new FileInputStream(filePath);
                return importData(inputStream, dataClass, moreSheet);
            }
        } catch (FileNotFoundException e) {
            log.error(e.getMessage(), e);
        } finally {
            try {
                if (VerifyUtil.nonNull(inputStream)) {
                    inputStream.close();
                }
            } catch (IOException e) {
                log.error(e.getMessage(), e);
            }
        }
        return null;
    }

    /**
     * 通过输入流获取excel数据
     *
     * @param inputStream 文件路径
     * @param dataClass   转换的对象
     * @param moreSheet   是否是多sheet页
     */
    private static <E> List<E> importData(InputStream inputStream, Class<E> dataClass, boolean moreSheet) {
        Workbook workbook = null;
        try {
            if (VerifyUtil.nonNull(inputStream)) {
                // 通过缓冲流导入数据
                workbook = StreamingReader.builder().rowCacheSize(MAX_ROW_NUM).bufferSize(BUFFER_SIZE).open(inputStream);
                return getSheetData(workbook, dataClass, moreSheet);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        } finally {
            try {
                if (VerifyUtil.nonNull(inputStream)) {
                    inputStream.close();
                }
            } catch (IOException e) {
                log.error(e.getMessage(), e);
            }
            try {
                if (VerifyUtil.nonNull(workbook)) {
                    workbook.close();
                }
            } catch (IOException e) {
                log.error(e.getMessage(), e);
            }
        }
        return null;
    }

    /**
     * 获取sheet页数据
     *
     * @param workbook  工作簿对象
     * @param dataClass 转换的对象
     * @param moreSheet 是否是多sheet页
     */
    private static <E> List<E> getSheetData(Workbook workbook, Class<E> dataClass, boolean moreSheet) {
        List<E> dataList = Lists.newArrayList();
        for (Sheet sheet : workbook) {
            log.debug("当前sheet页名称: {}", sheet.getSheetName());
            dataList.addAll(getDataList(sheet, dataClass));
            if (moreSheet)
                break;
        }
        return dataList;
    }

    /**
     * 获取当前Sheet页的数据
     *
     * @param sheet     sheet页对象
     * @param dataClass 转换的对象
     */
    private static <E> List<E> getDataList(Sheet sheet, Class<E> dataClass) {
        List<String> headList = Lists.newArrayList();
        List<E> dataList = Lists.newArrayList();
        int count = 1;
        for (Row row : sheet) {
            log.debug("当前行对象为{}",row);
            log.debug("当前行数: {}", count);
            if (count == 1) {
                headList.addAll(getHeadList(row));
            } else {
                E data = getFileData(row, headList, dataClass);
                if (VerifyUtil.nonNull(data)) {
                    dataList.add(data);
                }
            }
            count++;
        }
        return dataList;
    }

    /**
     * 获取定义的表头集合
     *
     * @param row 当前excel行对象
     */
    private static List<String> getHeadList(Row row) {
        ArrayList<String> headList = Lists.newArrayList();
        for (Cell cell : row) {
            headList.add(cell.getStringCellValue());
        }
        return headList;
    }

    /**
     * 获取行数据
     *
     * @param row       当前excel行对象
     * @param headList  定义的表头集合
     * @param fileClass 转换的对象
     */
    private static <E> E getFileData(Row row, List<String> headList, Class<E> fileClass) {
        Map<String, Object> dataMap = getDataMap(headList, row);
        E data = null;
        boolean isValid = false;
        try {
            data = fileClass.newInstance();
            Field[] fields = getAllField(data);
            for (Field field : fields) {
                // 获取转换对象的Excel注解, 通过注解的name属性获取对应的数据
                Excel excel = field.getAnnotation(Excel.class);
                if (excel == null) {
                    continue;
                }
                Object value = dataMap.get(excel.name());
                if (!isValid && VerifyUtil.nonNull(value)) {
                    isValid = true;
                }
                setValue(data, field, value);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return isValid ? data : null;
    }

    /**
     * 获取数据与标题对应的值Map
     *
     * @param headList 表头集合
     * @param row      当前行对象
     */
    private static Map<String, Object> getDataMap(List<String> headList, Row row) {
        Map<String, Object> dataMap = Maps.newHashMap();
        for (int i = 0; i < headList.size(); i++) {
            Object value = null;
            Cell cell = row.getCell(i);
            if (VerifyUtil.nonNull(cell)) {
                CellType cellType = cell.getCellType();
                if (VerifyUtil.nonNull(cellType)) {
                    switch (cellType) {
                        case STRING:
                            value = cell.getStringCellValue();
                            break;
                        case NUMERIC:
                            value = cell.getNumericCellValue();
                            break;
                        case FORMULA:
                            value = cell.getCellFormula();
                            break;
                        case BOOLEAN:
                            value = cell.getBooleanCellValue();
                            break;
                    }
                    dataMap.put(headList.get(i), value);
                }
            }
        }
        return dataMap;
    }

    /**
     * 获取当前对象的全部字段, 包括继承的对象字段
     *
     * @param object 转换对象
     */
    private static Field[] getAllField(final Object object) {
        Class<?> objectClass = object.getClass();
        Field[] currentFields = {};
        do {
            final Field[] fields = objectClass.getDeclaredFields();
            currentFields = arrayMerge(fields, currentFields);
            objectClass = objectClass.getSuperclass();
        } while (objectClass != Object.class);
        return currentFields;
    }

    private static <T> T[] arrayMerge(final T[] sourceArr, final T[] targetArr) {
        final int curSouArrLen = sourceArr.length;
        final int curTarArrLen = targetArr.length;
        T[] newTarArr = Arrays.copyOf(targetArr, (curSouArrLen + curTarArrLen));
        System.arraycopy(sourceArr, 0, newTarArr, curTarArrLen, curSouArrLen);
        return newTarArr;
    }

    /**
     * 设置值, 对excel的值做转换
     *
     * @param data  转换的对象实例
     * @param field 转换的对象当前字段
     * @param value 赋值对象
     */
    private static <E> void setValue(E data, Field field, Object value) {
        if (value == null) {
            return;
        }
        try {
            field.setAccessible(true);
            Class<?> type = field.getType();
            if (type.isAssignableFrom(BigDecimal.class)) {
                String valueStr = value.toString();
                if (VerifyUtil.isNotBlank(valueStr)) {
                    field.set(data, new BigDecimal(valueStr));
                }
            } else if (type.isAssignableFrom(Long.class)) {
                String valueStr = value.toString();
                if (VerifyUtil.isNotBlank(valueStr)) {
                    field.set(data, Long.parseLong(value.toString()));
                }
            } else if (type.isAssignableFrom(Integer.class)) {
                String valueStr = value.toString();
                if (VerifyUtil.isNotBlank(valueStr)) {
                    field.set(data, Integer.parseInt(value.toString()));
                }
            } else if (type.isAssignableFrom(String.class)) {
                if (value instanceof Double) {
                    value = String.valueOf(((Double) value).longValue());
                }
                field.set(data, value);
            }
        } catch (IllegalAccessException e) {
            log.error(e.getMessage(), e);
        }
    }
}

标签:return,excel,value,inputStream,static,导入,报错,param,dataClass
From: https://blog.51cto.com/u_12266412/8904079

相关文章

  • mapstruct报错 No property named "XXXX" exists in source parameter(s). Type "XXXX
    1、问题现象java:Nopropertynamed"XXXX"existsinsourceparameter(s).Type"XXXX"hasnoproperties.2、相关环境依赖版本jdk:17maven:3.8.8springboot:3.1.4lombok:1.18.30mapstruct:1.5.53、解决办法在pom.xml中加入如下配置<annotationProcessor......
  • 网页在线编辑Excel表格,调用本机Office,非模拟,插入图片,导出PDF全屏编辑
    Excel作为微软Office的重要组成部分,在各行业中应用非常广泛,随着互联网及云计算的普及,网页在线编辑Excel表格也越来越成文更多人的广泛需求,而在网页中却无法直接在线编辑微软Office,下面介绍一种Web网页在线编辑Excel表格方案,可以调用本机原生Offce软件,直接在网页上编辑Excel表格。......
  • openGauss学习笔记-165 openGauss 数据库运维-备份与恢复-导入数据-使用COPY FROM STD
    openGauss学习笔记-165openGauss数据库运维-备份与恢复-导入数据-使用COPYFROMSTDIN导入数据-通过本地文件导入导出数据165.1示例1:通过本地文件导入导出数据在使用JAVA语言基于openGauss进行二次开发时,可以使用CopyManager接口,通过流方式,将数据库中的数据导出到本地文件或者......
  • pip的一种报错
    最近在使用pip镜像源下载东西时,报错。报错信息WARNING:Therepositorylocatedatpypi.douban.comisnotatrustedorsecurehostandisbeingignored.IfthisrepositoryisavailableviaHTTPSwerecommendyouuseHTTPSinstead,otherwiseyoumaysilencethis......
  • 前端json转excel 到zip下载
    问题描述:后端返回数据原先返回是多个json文件的压缩包二进制文件流,前端直接下载二进制文件流。但是客户要求下载excel类型文件。解决方案:前端拿到表格的json数据转换成对应table的html字符串,使用插件js-xlsx。给个链接,import*asXLSXfrom'xlsx'//JSONData为导出的json数......
  • python中导入模块/包的几种方式
    一、模块的导入方式模块就是.py类型的Python文件导入时不需要.py后缀,直接导入文件名即可1.利用import直接导入:语法:importmodule_name使用方式:module_name.class_name或者module.func_name2.利用import导入模块并设置一个别名语法:importmodule_nameasXXX使用方式:XXX.cl......
  • android 接入 GreenDao 报错Unresolved reference: DaoMaster
    这是我在51CTO博客的第一篇博文。大家好,我是永远的回忆丶,混迹移动端多年的安卓开发工程师。今天我来分享一个踩坑记录,关于GreenDao接入的问题。出现场景:接入GreenDao并且使用更多插件之后,很容易产生报错Unresolvedreference:DaoMaster解决方法:plugins{id'com.android.......
  • 打工笔记--------------------winform程序报错CLR20r3签名System.I0.IOException
    先看问题编写了一个程序在我本机运行没有问题,放到别人电脑上就有可能报这种错误System.I0.IOException  首先我问了一下ChatPgt:他说:CLR20r3是一个通用的错误代码,表示在.NETFramework中发生了未处理的异常。System.IO.IOException是与输入/输出操作相关的一个常见......
  • 启用微服务报错:Method has too many Body parameters
    启用微服务报错:MethodhastoomanyBodyparameterspackagecom.llq.springcloud.controller;@RestControllerpublicclassStorageController{@ResourceprivateStorageServicestorageService;//扣减库存你@PostMapping("/storage/reduce")......
  • 启动微服务报错:java.lang.IllegalStateException: Service id not legal hostname (se
    Order微服务通过opneFeign调用storage和account时报错原因分析:服务名称不能有下划线,可以使用中划线,Springcloud无法识别下划线,将下划线改为中划线即可注意:这个改了之后,你在进行远程调用的时候,接口对应的方法接口也需要相应改变【分布式开发,一个微服务模块修改了,很可能......