java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java接收解析excel方法及注意

Java接收解析excel方法及注意事项说明

作者:ArrowL3Zz

这篇文章主要介绍了Java接收解析excel方法及注意事项说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

前言

提示:本文着重讲解java如何处理excel:

例如:本文从java接收excel,解析excel,以及业务场景中基于阻塞队列处理大批量的Excel。

提示:以下是本篇文章正文内容,下面案例可供参考

一、Java接收Excel

示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。

1.引入库

pom如下:

       <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.17</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.15</version>
        </dependency>
        <dependency>
            <groupId>commons-beanutils</groupId>
            <artifactId>commons-beanutils</artifactId>
            <version>1.9.3</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.21</version>
        </dependency>

2.Controller层代码

提示: 本文MultipartFile接收,请求方式为form表单提交

       /**
     * 传入excel
     *
     * @return
     */
    @PostMapping(value = "/inputExcel", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    @ApiOperation("传入excel")
    public R inputExcel(@RequestPart("file") MultipartFile file) {
        InputExcelDTO inputExcelDTO = new InputExcelDTO();
        inputExcelDTO.setFile(file);
        if (Objects.isNull(inputExcelDTO.getExcelName()) || Objects.isNull(inputExcelDTO.getFile())) {
            return R.failed("必填参数不可为空");
        }
        return excelService.inputExcel(inputExcelDTO);
    }

二、解析excel

1.将MultipartFile 转 File作为临时文件存储在本地,解析

代码如下:

工具类 :

package com.byt.form.convert.util;

import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author: author
 * @date: 2021/8/27 8:46
 * @description: excel处理工具类
 */
public class ExcelDealUtils {
    /**
     * MultipartFile 转 File
     *
     * @param file
     * @throws Exception
     */
    public static File multipartFileToFile(MultipartFile file) throws Exception {

        File toFile = null;
        if (file.equals("") || file.getSize() <= 0) {
            file = null;
        } else {
            InputStream ins = null;
            ins = file.getInputStream();
            toFile = new File(file.getOriginalFilename());
            inputStreamToFile(ins, toFile);
            ins.close();
        }
        return toFile;
    }


    //获取流文件
    private static void inputStreamToFile(InputStream ins, File file) {
        try {
            OutputStream os = new FileOutputStream(file);
            int bytesRead = 0;
            byte[] buffer = new byte[8192];
            while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.close();
            ins.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 删除本地临时文件
     *
     * @param file
     */
    public static void deleteTempFile(File file) {
        if (file != null) {
            File del = new File(file.toURI());
            del.delete();
        }
    }


    /**
     * 处理数据
     *
     * @param str
     * @return
     */
    public static String getDelDay(String str) {
        str = str.trim();
        String reg = "[\u4e00-\u9fa5]";
        Pattern pat = Pattern.compile(reg);
        Matcher mat = pat.matcher(str);
        String repickStr = mat.replaceAll("");
        return repickStr;
    }
}

ServiceImpl实现层

 File excel= ExcelDealUtils.multipartFileToFile(inputExcelDTO.getFile());
    try {
            //excel最后修改时间
            String excelTime = modTime;
            if (excel.isFile() && excel.exists()) {   //判断文件是否存在
                String[] split = excel.getName().split("\\."); //特殊字符转义
                Workbook wb;
                //根据文件后缀(xls/xlsx)进行判断
                if ("xls".equals(split[split.length - 1])) {
                    FileInputStream fis = new FileInputStream(excel);   //文件流对象
                    wb = new HSSFWorkbook(fis);
                    fis.close();
                } else if (("xlsx".equals(split[split.length - 1]))) {
                    ZipSecureFile.setMinInflateRatio(-1.0d);
                    FileInputStream fis = new FileInputStream(excel);
                    wb = new XSSFWorkbook(fis);
                    fis.close();
                } else {
                    log.info("文件类型错误");
                    return;
                }

                JSONArray data = new JSONArray();
                if (sheet == null) {
                    return;
                }
                log.info("处理sheet为{}", sheet.getSheetName());
                int firstRowIndex = sheet.getFirstRowNum();   //第一行是列名ABC...字母,所以不读
                int lastRowIndex = sheet.getLastRowNum();
                for (int rIndex = firstRowIndex; rIndex <= lastRowIndex; rIndex++) {   //遍历行
                    JSONArray rowArray = new JSONArray();
                    Row row = sheet.getRow(rIndex);
                    if (row != null) { //这里只保存了不为空的行
                        int firstCellIndex = row.getFirstCellNum();
                        int lastCellIndex = row.getLastCellNum();
                        for (int cIndex = firstCellIndex; cIndex < lastCellIndex; cIndex++) {   //遍历列
                            Cell cell = row.getCell(cIndex);
                            if (cell != null) {
                                rowArray.add(getCellFormatValue(cell));
                            } else {
                                rowArray.add("");
                            }
                        }
                    }
                    if (rowArray.size() > 5) {
                        data.add(rowArray);
                    }
                }

               //data为二维数组,顺序与excel一致
                wb.close();
            } else {
                log.info("找不到指定文件");
            }
        } catch (Exception e) {
            log.info("解析错误 报表id为{},错误日志为{}", excelId, e);
        }

    /**
     * 处理公式数据,如果是公式直接读值,excel日期解析到的是数字,需要转换成日期
     *根据项目情况处理
     * @param cell
     * @return
     */
    public static Object getCellFormatValue(Cell cell) {
        Object cellValue = null;
        if (cell != null) {
            //判断cell类型
            switch (cell.getCellType()) {
                case Cell.CELL_TYPE_NUMERIC: {
                    cell.setCellType(Cell.CELL_TYPE_STRING); //数字型特殊处理,使获取的整型不带有小数点
                    cellValue = cell.getRichStringCellValue().getString();
                    // cellValue = String.valueOf(cell.getNumericCellValue());
                    break;
                }
                case Cell.CELL_TYPE_FORMULA: {
                    //非法字符处理
                    try {
                        cellValue = cell.getStringCellValue();
                    } catch (Exception e) {
                        //特殊处理
                    }
                    try {
                        cellValue = String.valueOf(cell.getNumericCellValue());
                    } catch (Exception e) {
                    }
                    break;
                }
                case Cell.CELL_TYPE_STRING: {
                    cellValue = cell.getRichStringCellValue().getString();
                    break;
                }
                default:
                    cellValue = "";
            }
        } else {
            cellValue = "";
        }
        return cellValue;
    }


2.大批量的excel同时丢上来容易内存溢出,故用阻塞队列处理

全局参数:

  // 能容纳100个文件
    final BlockingQueue<File> queue = new LinkedBlockingQueue<File>(100);
    // 读个数
    final AtomicInteger rc = new AtomicInteger();

    //   final File exitFile = new File("");
    HashMap<String, DelFileBO> fileMap = new HashMap<>();

存入阻塞队列:

 /**
  *存入阻塞队列 
 */
 private void (File file){
 //存入Map,主要是为了避免线程同时处理多个,所以用map记录
        fileMap.put(delFile.getName(), file);
        //放入阻塞队列
        scanFile(delFile);
 } 

 public void scanFile(File file) {
        if (file.isDirectory()) {
            File[] files = file.listFiles(new FileFilter() {
                public boolean accept(File pathname) {
                    return pathname.isDirectory()
                            || pathname.getPath().endsWith(".java");
                }
            });
            for (File one : files)
                scanFile(one);
        } else {
            try {
                int index = rc.incrementAndGet();
                queue.put(file);
            } catch (InterruptedException e) {
            }
        }
    }

起一个线程从队列拿数据处理

 @PostConstruct
    public void delExcelFile() {

        taskExecutor.execute(() -> {
            while (true) {
                this.delFile();
            }
        });
    }


    public void delFile() {
        try {
            //从队列拿文件处理
            File file = queue.take();
            //业务逻辑
        } catch (InterruptedException e) {
            
        }
    }

总结

以上就是今天要讲的内容,本文仅仅简单介绍了java如何解析excel,针对自身业务也可以维护一些其余配置,如报表id以及处理方式等。

这些仅为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文