java大数据量导出csv文件并压缩

java大数据量导出csv文件并压缩

java使用POI大数据量导出excel一般会存在以下几个问题:

  • 一次从数据库查询出这么大数据,查询缓慢
  • 查询数据量过大时会内存溢出
    解决方案:分页查询数据,比如一次查询5w数据,生成多个excel文件
  • 大数据量生成excel文件过慢
    解决方案:生成excel改为生成csv文件

本文主要 介绍java 导出csv文件

  • csv文件导出工具类
package com.yss.datamiddle.util;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @description:
 * @author: Hld
 * @create: 2021/11/16 17:11
 * @update: 2021/11/16 17:11
 */
public class CsvUtils {


    /**
     * 导出csv文件
     * @param titles    导出文件列头
     * @param list      具体导出数据
     * @param fileName  文件名称
     * @param response
     * @throws IOException
     * @throws IllegalArgumentException
     * @throws IllegalAccessException
     */
    public static void exportCsv(List<String> titles, List<Map<String,Object>> list, String fileName, HttpServletResponse response) throws IOException, IllegalArgumentException, IllegalAccessException{
        StringBuffer expStr = new StringBuffer();
        OutputStream o = null;
        try {
            //csv文件是逗号分隔,除第一个外,每次写入一个单元格数据后需要输入逗号
            for(String title : titles){
                expStr.append(title).append(",");
            }
            //写完文件头后换行
            expStr.append("\n");
            //写内容
            for(Map<String,Object> map : list){
                for (String key : map.keySet()) {
                    String val = map.get(key) != null ? map.get(key).toString() : "";
                    expStr.append(val).append(",");
                }
                //写完一行换行
                expStr.append("\n");
            }
            response.setContentType("application/download;charset=UTF-8");
            response.setContentType("Content-type:application/vnd.ms-excel;charset=UTF-8");
            response.setHeader("Content-disposition","attachment;filename="+ java.net.URLEncoder.encode(fileName, "UTF-8"));
            o = response.getOutputStream();
            o.write(expStr.toString().getBytes("GBK"));
        } catch (Exception e){
            e.printStackTrace();
        }finally {
            // 关闭
            if(o != null){
                o.close();
            }
        }
    }

    /**
     * 导出csv压缩文件
     * @param titles    导出文件列头
     * @param list      具体导出数据
     * @param fileName  压缩文件名称 例:aa.zip
     * @param response
     * @throws IOException
     * @throws IllegalArgumentException
     * @throws IllegalAccessException
     */
    public static String exportCsvZip(List<String> titles, List<Map<String,Object>> list, String fileName, HttpServletResponse response) throws IOException, IllegalArgumentException, IllegalAccessException{
        StringBuffer expStr = new StringBuffer();
        ZipOutputStream zos = null;
        OutputStream o = null;
        try {
            //csv文件是逗号分隔,除第一个外,每次写入一个单元格数据后需要输入逗号
            for(String title : titles){
                expStr.append(title).append(",");
            }
            //写完文件头后换行
            expStr.append("\n");
            //写内容
            for(Map<String,Object> map : list){
                for (String key : map.keySet()) {
                    String val = map.get(key) != null ? map.get(key).toString() : "";
                    expStr.append(val).append(",");
                }
                //写完一行换行
                expStr.append("\n");
            }
            response.setContentType("application/download;charset=UTF-8");
            response.setContentType("Content-type:application/vnd.ms-excel;charset=UTF-8");
            response.setHeader("Content-disposition","attachment;filename=" + java.net.URLEncoder.encode(fileName, "UTF-8"));

            o = response.getOutputStream();
            zos =  new ZipOutputStream(new BufferedOutputStream(o));
            zos.putNextEntry(new ZipEntry(fileName.replace("zip","csv")));//创建压缩文件内的文件
            zos.write(expStr.toString().getBytes("GBK"));
            zos.closeEntry();
        } catch (Exception e){
            e.printStackTrace();
        }finally {
            if(zos != null){
                zos.close();
            }
            if(o != null){
                o.close();
            }
        }
        return "0";
    }
}

  • 调用示例
    @ApiOperation(value="导出csv文件")
    @PostMapping("/v1/exportCsv")
    public void exportCsv(HttpServletResponse response) throws IOException, IllegalAccessException {
        //模拟获取测试数据
        List<Map<String, Object>> datas = getDatas();
        // 导出文件列头
        List<String> titles = Arrays.asList("第一列title", "第二列title", "第三列title", "第四列title", "第五列title");
        // 导出csv文件
        CsvUtils.exportCsv(titles,datas,"test.csv",response);
        // 导出csv压缩文件
        CsvUtils.exportCsvZip(titles,datas,"test.zip",response);
       
    }
    
    public List<Map<String,Object>> getDatas(){
        List<Map<String,Object>> datas = new ArrayList<>();
        for (int i = 0; i < 10000; i++){
            Map<String,Object> map = new HashMap<>();
            map.put("a1","a1"+i);
            map.put("b2","b2"+i);
            map.put("c3","c3"+i);
            map.put("d4","d4"+i);
            map.put("e5","e5"+i);
            datas.add(map);
        }
        return datas;
    }

亲测导出40w数据到csv耗时3s左右

你可能感兴趣的:(代码文档,csv导出,大数据量,压缩)