Java使用csv导出多字段大数据文件(无需写实体映射,自动遍历)

  1. csv工具类ExcelCsvUtils xls、xlsx、csv通用格式工具类
    此处使用LinkedHashMap链表哈希表,实现键值中值为空时仍存在数据以及保证顺序与sql顺序一致。
    mapper.xml 中需要设置返回类型为:resultType="java.util.LinkedHashMap"
package com.xxx.xxx.utils;

import lombok.val;
import org.springframework.util.CollectionUtils;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;

public class ExcelCsvUtils {
    /**
     * CSV文件列分隔符
     */
    private static final String CSV_COLUMN_SEPARATOR = ",";

    /**
     * CSV文件行分隔符
     */
    private static final String CSV_ROW_SEPARATOR = "\r\n";

    /**
     * @param dataList 集合数据
     * @param titles   表头部数据
     * @param keys     表内容的键值
     * @param os       输出流
     */
    public static void doExport(List<LinkedHashMap<String, String>> 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.isEmpty(dataList)) {
            for (Map<String, String> data : dataList) {
                for (String key : keyArr) {
                    buf.append(ExcelCsvUtils.handleFormatValue(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));
    }

    // 处理数据
    private static String handleFormatValue(Object data) {
        if (data == null) {
            return "";
        }
        String val = data.toString();

        // 如果数据中含有 " 则在 "外层再包一层 ""
        if (val.contains("\"") ){
            val=val.replace("\"", "\"\"");
        }

        // 如果数据中含有 , 则在 , 外层再包一层 ""
        if (val.contains(",")) {
            val = "\""+val+"\"";
        } else {
            // \t 是为了处理字符串的日期类型数据导出显示异常
            val = "\t" + val;
        }

        return val;
    }
}

  1. 修改ymlmybatis配置 根据实际情况修改call-setters-on-nullstrue即可
mybatis-plus:
  # 扫描mapper.xml文件
  mapper-locations: classpath:mapper/*/*.xml,classpath:mapper/system_settings/*/*/*.xml
  # 扫描实体类
  typeAliasesPackage: com.sun.system.entity
  # 主键类型
  global-config:
    #配置逻辑删除字段为1是删除
    logic-delete-value: 1
    #配置逻辑删除字段为0是未删除
    logic-not-delete-value: 0
    #主键类型  0:"数据库ID自增", 1:"用户输入ID",2:"全局唯一ID (数字类型唯一ID)", 3:"全局唯一ID UUID";
    id-type: 1
    # Sequence序列接口实现类配置
    key-generator: com.baomidou.mybatisplus.incrementer.OracleKeyGenerator
    #字段策略 0:"忽略判断",1:"非 NULL 判断"),2:"非空判断"
    field-strategy: 0
    #驼峰下划线转换
    db-column-underline: true
    #刷新mapper 调试神器
    refresh-mapper: true
    #数据库大写下划线转换
    #capital-mode: true
  #自定义SQL注入器
  configuration:
    # 是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN(下划线命名) 到经典 Java 属性名 aColumn(驼峰命名) 的类似映射
    map-underscore-to-camel-case: true
    # 全局地开启或关闭配置文件中的所有映射器已经配置的任何缓存,默认为 true
    cache-enabled: true
    #懒加载
    #aggressive-lazy-loading: true
    #NONE:不启用自动映射 PARTIAL:只对非嵌套的 resultMap 进行自动映射 FULL:对所有的 resultMap 都进行自动映射
    #auto-mapping-behavior: partial
    #NONE:不做任何处理 (默认值设置)WARNING:以日志的形式打印相关警告信息 FAILING:当作映射失败处理,并抛出异常和详细信息
    #auto-mapping-unknown-column-behavior: none
    #如果查询结果中包含空值的列,则 MyBatis 在映射的时候,不会映射这个字段
    call-setters-on-nulls: true
    # 这个配置会将执行的sql打印出来,在开发或测试的时候可以用
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

mybatis:
  configuration:
    call-setters-on-nulls: true
  1. controller查询后导出
    /**
     * 生成Excel/CSV blob数据并返回前台
     * @param response 响应数据
     * @param data 前台参数
     * @throws Exception 异常信息 已抛出
     */
    @RequestMapping(value = "generateHomeExcelCSV",method = {RequestMethod.POST},produces = {"text/plain;charset=UTF-8"})
    public void generateHqmsCSV(HttpServletResponse response,@RequestBody Map<String,Object> data) throws Exception {
        ServletOutputStream outputStream = response.getOutputStream();
        String keys = "";
        List<LinkedHashMap<String, String>> dataList = xxxMapper.getxxx(data);
        // 遍历Map获取所有的键和值
        for (Map.Entry<String, String> entry : dataList.get(0).entrySet()) {
            keys += entry.getKey()+",";
        }
        keys = removeTrailingComma(keys);
        ExcelCsvUtils.doExport(dataList,keys,keys,
                outputStream);
    }

	
    /**
     * 检查字符串是否以逗号结尾,如果是,则去掉最后一个字符(即逗号)
     * @param str
     * @return
     */
    public static String removeTrailingComma(String str) {
        if (str.endsWith(",")) {
            return str.substring(0, str.length() - 1);
        }
        return str;
    }
  1. 前台正常http请求后台方法,并将返回数据处理为blob后导出即可
this.$http
        .post("xxx/xxx/generateHomeExcelCSV", { 'outEndTime': this.where.outEndTime, 'outStartTime': this.where.outStartTime })
        .then((res) => {
        	/**
         	* 关闭加载框
         	*/
        	loading.close();
        	// 处理数据,并下载
        	const blob = new Blob([res.data]);
        	let url = window.URL.createObjectURL(blob)
        	let link = document.createElement('a')
        	link.href = url
        	link.setAttribute('download', 'xxxx'+Date.now()+'.csv')
        	document.body.appendChild(link)
        	link.click()
        })
        .catch((e) => {
          /**
           * 关闭加载框
           */
          loading.close();
          this.$message.error(e.message);
        });
  1. 完工,回家睡觉🤣
  2. END
  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Java中,我们可以使用一些工具来将文件中的字段映射实体类中。以下是常用的两种方法: 1. 手动读取文件并解析数据 这种方法需要我们手动读取文件,并解析文件中的数据,然后将数据存储到对应的实体类中。具体步骤如下: - 使用Java IO读取文件,并逐行读取文件中的数据。 - 对于每一行数据,我们使用String.split()方法将其分割为多个字段。 - 将字段映射实体类中,并将实体类存储到列表中。 以下是一个示例代码: ```java public class EntityMapper { public List<Entity> mapFileToEntity(String fileName) throws IOException { List<Entity> entities = new ArrayList<>(); try (BufferedReader br = new BufferedReader(new FileReader(fileName))) { String line; while ((line = br.readLine()) != null) { String[] fields = line.split(","); Entity entity = new Entity(); entity.setField1(fields[0]); entity.setField2(fields[1]); //... entities.add(entity); } } return entities; } } ``` 2. 使用第三方库 除了手动读取文件之外,我们还可以使用一些第三方库来帮助我们将文件中的字段映射实体类中。其中比较常用的是Apache Commons CSV和OpenCSV。这些库可以帮助我们轻松地读取和解析CSV格式的文件,并将数据映射Java对象中。以下是一个使用OpenCSV的示例代码: ```java public class EntityMapper { public List<Entity> mapFileToEntity(String fileName) throws IOException { List<Entity> entities = new ArrayList<>(); try (CSVReader reader = new CSVReader(new FileReader(fileName))) { String[] header = reader.readNext(); BeanListProcessor<Entity> processor = new BeanListProcessor<>(Entity.class); CsvToBeanBuilder<Entity> builder = new CsvToBeanBuilder<>(reader); builder.withSeparator(',') .withHeader(header) .withType(Entity.class) .withIgnoreLeadingWhiteSpace(true) .withProcessor(processor); List<Entity> list = processor.getBeans(); entities.addAll(list); } return entities; } } ``` 在以上示例中,我们使用了OpenCSV库中的CsvToBeanBuilder类来将CSV格式的文件中的字段映射Java对象中。可以看到,使用第三方库可以使代码更加简洁和易于维护。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程似锦吖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值