前言

大家在做项目的时候,是不是经常会遇到一种需求,那就是导出excel表格,导入excel表格。

一、简单介绍一下CSV和excel的区别?

  • CSV是纯文本文件,excel不是纯文本,excel包含很多格式信息在里面。
  • CSV文件的体积会更小,创bai建分发读取更加方便,适合存放结构化信息,比如记录的导出,流量统计等等。
  • CSV文件在windows平台默认的打开方式是excel,但是它的本质是一个文本文件。

二、CSV导入和导出

1.引入jar包

<!-- csv依赖 -->
<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-csv</artifactId>
  <version>1.7</version>
</dependency>
<!-- 上传工具依赖 -->
<dependency>
  <groupId>commons-fileupload</groupId>
  <artifactId>commons-fileupload</artifactId>
  <version>1.4</version>
</dependency>

2.CSV导入

代码如下(示例):

    @ApiOperation("csv 导入")
    @PostMapping(value = "csvImport")
    public Result csvImport(@RequestParam("file") MultipartFile file) {
       
        // 使用CSV工具类,生成file文件
        File csvFile = CsvImportUtil.uploadFile(file);
        // 将文件内容解析,存入List容器,List<String>为每一行内容的集合,6为CSV文件每行的总列数
        List<List<String>> lists = CsvImportUtil.readCSV(csvFile.getPath(), 6);

        lists.stream().forEach(info -> {
           // 处理业务逻辑代码
        });

        return result;
    }
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;


/**
 * csv 导入工具类
 * @author gdd
 */
public class CsvImportUtil {

    //上传文件的路径
    private final static URL PATH = Thread.currentThread().getContextClassLoader().getResource("");


    /**
     * @return File  一般文件类型
     * @Description 上传文件的文件类型
     * @Param multipartFile
     **/
    public static File uploadFile(MultipartFile multipartFile) {
        // 获 取上传 路径
        String path = PATH.getPath() + multipartFile.getOriginalFilename();
        try {
            // 通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例
            File file = new File(path);
            // 此抽象路径名表示的文件或目录是否存在
            if (!file.getParentFile().exists()) {
                // 创建由此抽象路径名命名的目录,包括任何必需但不存在的父目录
                file.getParentFile().mkdirs();
            }
            // 转换为一般file 文件
            multipartFile.transferTo(file);

            return file;
        } catch (IOException e) {

            e.printStackTrace();
            return null;
        }

    }

    /**
     * @return List<List<String>>
     * @Description 读取CSV文件的内容(不含表头)
     * @Param filePath 文件存储路径,colNum 列数
     **/
    public static List<List<String>> readCSV(String filePath, int colNum) {
        BufferedReader bufferedReader = null;
        InputStreamReader inputStreamReader = null;
        FileInputStream fileInputStream = null;

        try {
            fileInputStream = new FileInputStream(filePath);
            inputStreamReader = new InputStreamReader(fileInputStream, "GBK");
            bufferedReader = new BufferedReader(inputStreamReader);

            CSVParser parser = CSVFormat.DEFAULT.parse(bufferedReader);


            //  表内容集合,外层 List为行的集合,内层 List为字段集合
            List<List<String>> values = new ArrayList<>();


            int rowIndex = 0;
            // 读取文件每行内容

            for (CSVRecord record : parser.getRecords()) {
                //  跳过表头
                if (rowIndex == 0) {
                    rowIndex++;
                    continue;
                }
                // 判断下角标是否越界
                if (colNum > record.size()) {
                    // 返回空集合
                    return values;
                }
                //  每行的内容
                List<String> value = new ArrayList<>();
                for (int i = 0; i < colNum; i++) {
                    value.add(record.get(i));
                }
                values.add(value);
                rowIndex++;
            }
            return values;
        } catch (IOException e) {
            e.printStackTrace();

        } finally {
            //关闭流
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (inputStreamReader != null) {
                try {
                    inputStreamReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fileInputStream != null) {
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }
}

3.CSV导出

代码如下(示例):

    @ApiOperation("csv 导出")
    @PostMapping(value = "exportCsv")
    public Result exportCsv(HttpServletResponse response) {
 
        try {
           
            // 查询需要导出的数据
         
            // 构造导出数据结构
            // 设置表头
            String titles = "id,姓名,爱好,地址,公司,年龄";
            // 设置每列字段
            String keys = "id,name,likeInfo,address,company,age";

            // 构造导出数据
            List<Map<String, Object>> datas = new ArrayList<>();
            Map<String, Object> mapInfo;

            if (ListUtils.isNotBlank(查询需要导出的数据)) {
                for (对象 data : 查询需要导出的数据) {
                    mapInfo = new HashMap<>(8);
                    mapInfo.put("id", data.getId());
                    mapInfo.put("name", data.getName());
                    mapInfo.put("likeInfo", data.getLikeInfo());
                    mapInfo.put("address", data.getAddress());
                    mapInfo.put("company", data.getCompany());
                    mapInfo.put("age", data.getAge());
                    datas.add(mapInfo);
                }
            }

            // 设置导出文件前缀
            String fName = "统计_";

            // 文件导出
            OutputStream os = response.getOutputStream();
            CsvExportUtil.responseSetProperties(fName, response);
            CsvExportUtil.doExport(datas, titles, keys, os);
            os.close();
        } catch (Exception e) {
            log.error("导出失败" + e.getMessage(), e);
        }

        return result;
    }

 

import com.sun.deploy.net.URLEncoder;
import org.apache.commons.collections4.CollectionUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * csv 导出工具类
 * @author gdd
 */
public class CsvExportUtil {
    /**
     * CSV文件列分隔符
     */
    private static final String CSV_COLUMN_SEPARATOR = ",";

    /**
     * CSV文件行分隔符
     */
    private static final String CSV_ROW_SEPARATOR = System.lineSeparator();

    /**
     * @param dataList 集合数据
     * @param titles   表头部数据
     * @param keys     表内容的键值
     * @param os       输出流
     */
    public static void doExport(List<Map<String, Object>> dataList, String titles, String keys, OutputStream os) throws Exception {

        // 保证线程安全
        StringBuffer buf = new StringBuffer();

        String[] titleArr = null;
        String[] keyArr = null;

        titleArr = titles.split(",");
        keyArr = keys.split(",");

        // 组装表头
        for (String title : titleArr) {
            buf.append(title).append(CSV_COLUMN_SEPARATOR);
        }
        buf.append(CSV_ROW_SEPARATOR);

        // 组装数据
        if (CollectionUtils.isNotEmpty(dataList)) {
            for (Map<String, Object> data : dataList) {
                for (String key : keyArr) {
                    buf.append(data.get(key)).append(CSV_COLUMN_SEPARATOR);
                }
                buf.append(CSV_ROW_SEPARATOR);
            }
        }

        // 写出响应
        os.write(buf.toString().getBytes("UTF-8"));
        os.flush();
    }

    /**
     * 设置Header
     *
     * @param fileName
     * @param response
     * @throws UnsupportedEncodingException
     */
    public static void responseSetProperties(String fileName, HttpServletResponse response) throws UnsupportedEncodingException {
        // 设置文件后缀
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        String fn = fileName + sdf.format(new Date()) + ".csv";
        // 读取字符编码
        String utf = "UTF-8";

        // 设置响应
        response.setContentType("application/ms-txt.numberformat:@");
        response.setCharacterEncoding(utf);
        response.setHeader("Pragma", "public");
        response.setHeader("Cache-Control", "max-age=30");
        response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fn, utf));
    }
}

总结

希望本文章可以帮助你解决工作中的导入和导出功能

欢迎大家关注

 

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐