1、前言

​ CSV,逗号分隔值(Comma-Separated Values),即为逗号分隔的文本文件。如果值中含有逗号、换行符、制表符(Tab)、单引号及双引号,则需要用双引号括起来;如果值中包含双引号,则需要用两个双引号来替换。

​ CSV大量用于不同系统之间的数据交换,是一种非常常用的文件格式。

​ 在Spring Boot项目中,将数据导出成CSV格式文件是常见的功能。与Excel文件导出类似,此处也用代码框架式的方式实现CSV文件导出,使得代码具有可重用性,并保持导出数据转换的灵活性。

2、基本框架

​ 基本框架包括一个接口类CsvExportable和一个CSV文件导出处理类CsvExportHandler,以及支持CsvExportable接口类的实体类。与基类相比,使用接口类的好处是实体类可以实现多个接口类,而没有多重继承的问题。

2.1、CSV文件导出处理类CsvExportHandler

​ CsvExportHandler类的代码如下:

package com.abc.questInvest.csv;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.util.List; /**
* @className : CsvExportHandler
* @description : CSV文件导出处理类
*
*/
public class CsvExportHandler<T extends CsvExportable> { /**
*
* @methodName : exportCsvFile
* @description : 导出CSV文件
* @param rowDataList : T类型对象列表
* @param csvFilePath : 输出的CSV文件路径
* @throws Exception : 异常发生时,抛出
*
*/
public void exportCsvFile(List<T> rowDataList,String csvFilePath)
throws Exception{ if (rowDataList.size() == 0) {
//必须要有导出数据,否则创建标题列失败
throw new Exception("无导出数据.");
} //取得第一个对象
T rowDataObj = rowDataList.get(0); //将数据写入csv格式文件
writeToCsv(rowDataList,rowDataObj,csvFilePath);
} /**
*
* @methodName : writeToCsv
* @description : 将数据写入csv格式文件
* @param dataList : T类型对象列表
* @param rowDataObj: T类型对象
* @param filePath : 输出的文件路径
* @throws Exception : 异常发生时,抛出
*
*/
private void writeToCsv(List<T> dataList, T rowDataObj, String filePath) throws Exception {
FileOutputStream fos = null;
BufferedOutputStream bos = null;
String enter = "\r\n";
String sLine;
StringBuffer write ;
fos = new FileOutputStream(new File(filePath));
bos = new BufferedOutputStream(fos);
//标题行
sLine = rowDataObj.outputCsvTitleLine();
write = new StringBuffer();
write.append(sLine);
//加换行符
write.append(enter);
bos.write(write.toString().getBytes("UTF-8"));
for (int i = 0; i < dataList.size(); i++) {
write = new StringBuffer();
T rowData = dataList.get(i);
//输出CSV格式的数据行
sLine = rowData.outputCsvDataLine();
//写数据行
write.append(sLine);
//加换行符
write.append(enter);
bos.write(write.toString().getBytes("UTF-8"));
}
//刷新数据
bos.flush(); //关闭流
bos.close();
fos.close();
}
}

​ CsvExportHandler支持泛型T,T限定必需支持CsvExportable接口类。只要实体类实现CsvExportable类的接口方法,就可以利用CsvExportHandler的方法实现CSV文件导出。

2.2、可CSV导出的接口类CsvExportable

​ CsvExportable类的代码如下:

package com.abc.questInvest.csv;

/**
* @className : CsvExportable
* @description : CSV导出对象接口类
*
*/
public interface CsvExportable {
/**
*
* @methodName : outputTitleLine
* @description : 输出标题行字符串
* @return : 标题行字符串
*
*/
public String outputCsvTitleLine(); /**
*
* @methodName : outputDataLine
* @description : 输出数据行
* @return : 符合CSV格式的数据行字符串
*
*/
public String outputCsvDataLine(); /**
*
* @methodName : CSVFormat
* @description : 将输入字符串格式化成CSV格式的字符串
* @param input : 输入字符串
* @return : 符合CSV格式的字符串
*
*/
public static String CSVFormat(String input) {
boolean bFound = false;
//如果值中含有逗号、换行符、制表符(Tab)、单引号,双引号,则需要用双引号括起来;
//如果值中包含双引号,则需要用两个双引号来替换。
//正则匹配:",'\"\r\n\t"
bFound = input.matches("(.*)(,|'|\"|\r|\n|\t)(.*)");
if (bFound) {
//如果存在匹配字符
//先将双引号替换为两个双引号
String sTemp = input.replaceAll("\"", "\"\"");
//然后,两端使用"字符
sTemp ="\"" + sTemp + "\"";
return sTemp;
}
return input;
}
}

​ CsvExportable类定义了2个接口方法:

  • outputCsvTitleLine方法,输出标题行字符串。

  • outputCsvDataLine方法,输出数据行字符串。

​ CsvExportable类还提供了一个静态方法:

  • CSVFormat方法,将字符串格式化成CSV格式的字符串。针对包含特殊字符的输入字符串进行特别处理。

2.3、实体类例子

​ 对需要导出CSV文件的现有的实体类进行改造,使之支持CsvExportable接口类。

​ 实体类为AnswerInfo,代码如下:

package com.abc.questInvest.entity;

import java.util.Date;

import javax.persistence.Column;

import com.abc.questInvest.csv.CsvExportable;
import com.abc.questInvest.excel.ExcelExportable; import lombok.Data; /**
* @className : AnswerInfo
* @description : 答卷信息类,支持CSV格式数据导出
*
*/
@Data
public class AnswerInfo implements CsvExportable {
// 记录id
@Column(name = "rec_id")
private Integer recId; // 发布任务id
@Column(name = "task_id")
private Integer taskId; // 问卷id
@Column(name = "questionnaire_id")
private Integer questionnaireId; // 问题编号
@Column(name = "question_no")
private Integer questionNo; // 答案
@Column(name = "answer")
private String answer; //========记录操作信息================
// 操作人姓名
@Column(name = "login_name")
private String loginName; // 记录删除标记,保留
@Column(name = "delete_flag")
private Byte deleteFlag; // 创建时间
@Column(name = "create_time")
private Date createTime; // 更新时间
@Column(name = "update_time")
private Date updateTime; //========实现CsvExportable接口================
/**
*
* @methodName : outputTitleLine
* @description : 输出标题行字符串
* @return : 标题行字符串
*
*/
@Override
public String outputCsvTitleLine() {
String title = "问卷ID,发布任务ID,记录ID,题号,答案";
return title;
} /**
*
* @methodName : outputDataLine
* @description : 输出数据行
* @return : 符合CSV格式的数据行字符串
*
*/
@Override
public String outputCsvDataLine() {
String dataLine = "";
//如果预计字符串可能包含双引号,则需要调用CSVFormat方法处理
dataLine = "" + questionnaireId + ","
+ taskId + ","
+ recId + ","
+ questionNo + ","
+ CsvExportable.CSVFormat(answer);
return dataLine;
}
}

2.4、单元测试

​ 下面进行CSV文件导出的单元测试。测试代码如下:

package com.abc.questInvest.csv;

import java.util.ArrayList;
import java.util.List; import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner; import com.abc.questInvest.entity.AnswerInfo;
import com.abc.questInvest.excel.ExcelExportHandler; /**
* @className : CsvExportHandlerTest
* @description : CSV文件导出测试
*
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class CsvExportHandlerTest {
@Test
public void exportCsvFileTest() {
CsvExportHandler<AnswerInfo> csvExport = new CsvExportHandler<AnswerInfo>();
List<AnswerInfo> dataList = new ArrayList<AnswerInfo>(); AnswerInfo item = new AnswerInfo();
item.setQuestionnaireId(1);
item.setTaskId(1);
item.setRecId(1);
item.setQuestionNo(1);
item.setAnswer("'A,B,C',A");
dataList.add(item); item = new AnswerInfo();
item.setQuestionnaireId(1);
item.setTaskId(1);
item.setRecId(1);
item.setQuestionNo(2);
item.setAnswer("B");
dataList.add(item); //有单引号和逗号
item = new AnswerInfo();
item.setQuestionnaireId(1);
item.setTaskId(1);
item.setRecId(1);
item.setQuestionNo(3);
item.setAnswer("'A,B,c',A");
dataList.add(item); //有逗号
item = new AnswerInfo();
item.setQuestionnaireId(1);
item.setTaskId(1);
item.setRecId(2);
item.setQuestionNo(1);
item.setAnswer(",B,");
dataList.add(item); //有tab符号
item = new AnswerInfo();
item.setQuestionnaireId(1);
item.setTaskId(1);
item.setRecId(2);
item.setQuestionNo(2);
item.setAnswer("\tB");
dataList.add(item); //有双引号和逗号
item = new AnswerInfo();
item.setQuestionnaireId(1);
item.setTaskId(1);
item.setRecId(2);
item.setQuestionNo(3);
item.setAnswer("\"abc\",C");
dataList.add(item); String property = System.getProperty("user.dir");
String filePath = property + "\\answer_data_Q1_T1.csv"; try {
csvExport.exportCsvFile(dataList,filePath);
}catch(Exception e) {
e.printStackTrace();
}
}
}

​ 执行测试,结果生成了answer_data_Q1_T1.csv文件,用文本编辑器打开,内容如下:

问卷ID,发布任务ID,记录ID,题号,答案
1,1,1,1,"'A,B,C',A"
1,1,1,2,B
1,1,1,3,"'A,B,c',A"
1,1,2,1,",B,"
1,1,2,2," B"
1,1,2,3,"""abc"",C"

​ 可见导出的是CSV格式的数据。

Spring Boot下的一种导出CSV文件的代码框架的更多相关文章

  1. Spring Boot下的一种导出Excel文件的代码框架

    1.前言 ​ 在Spring Boot项目中,将数据导出成Excel格式文件是常见的功能.与Excel文件导入类似,此处也用代码框架式的方式实现Excel文件导出,使得代码具有可重用性,并保持导出数据 ...

  2. Spring Boot下的一种导入Excel文件的代码框架

    1.前言 ​ Spring Boot下如果只是导入一个简单的Excel文件,是容易的.网上类似的文章不少,有的针对具体的实体类,代码可重用性不高:有的利用反射机制或自定义注解,开发了Excel导入工具 ...

  3. PHP 导出 CSV 文件用 Excel 打开出现中文乱码

    本篇文章由:http://xinpure.com/php-export-csv-file-opened-by-excel-appear-garbled/ 乱码情况 写了一段导出 CSV 文件的代码,可 ...

  4. Spring Boot下Druid连接池+mybatis

      目前Spring Boot中默认支持的连接池有dbcp,dbcp2, hikari三种连接池.  引言: 在Spring Boot下默认提供了若干种可用的连接池,Druid来自于阿里系的一个开源连 ...

  5. 创建Spring Boot项目的几种方式总结

    一.我们可以使用Spring Initializr来创建SpringBoot项目. Spring Initializr从本质上来说就是一个Web应用程序,它能为你生成Spring Boot项目结构.虽 ...

  6. Spring Boot2 系列教程(二)创建 Spring Boot 项目的三种方式

    我最早是 2016 年底开始写 Spring Boot 相关的博客,当时使用的版本还是 1.4.x ,文章发表在 CSDN 上,阅读量最大的一篇有 43W+,如下图: 2017 年由于种种原因,就没有 ...

  7. spring boot下为配置属性值加密的正确姿势

    最近做电商系统,安全性要求比较高,针对配置属性值的加密自然也是需要增强的点之一,那么如何加密呢? 网上搜索了些,有jasypt加密mysql密码的最为普遍,可惜问题就在于只能加密mysql信息,其他的 ...

  8. spring boot下使用logback或log4j生成符合Logstash标准的JSON格式

    spring boot下使用logback或log4j生成符合Logstash标准的JSON格式 一.依赖 由于配置中使用了json格式的日志输出,所以需要引入如下依赖 "net.logst ...

  9. 运行 Spring Boot 应用的 3 种方式

    今天介绍 3 种运行 Spring Boot 应用的方式,看大家用过几种? 你所需具备的基础 什么是 Spring Boot? Spring Boot 核心配置文件详解 Spring Boot 开启的 ...

随机推荐

  1. 【转】java-selenium三种等待方式

    方式1: 线程等待:Thread.sleep(xxxx) 只要在case中加入sleep就会强制等待设置的时间后才会执行之后的命令,这种等待一般适用于调试脚本的时候. java代码: //等待3秒 T ...

  2. 02、SpringBoot2入门

    1.系统要求 Java 8 & 兼容java14 . Maven 3.3+ idea 2019.1.2 1.1.maven设置 <mirrors> <mirror> & ...

  3. javaWeb——Servlet(二)

    Servelet登录页面步骤: 浏览器访问http://127.0.0.1/login.html 浏览器通过form把账号和密码提交到/login(通过action),附带method="p ...

  4. shell练习(1)创建100个用户

    shell练习(1)创建100个用户 默默努力的小白. 2020-04-15 16:28:49 49 收藏文章标签: linuxshell版权随机创建100个用户,并生成随机密码,并将密码放入一个文件 ...

  5. docker部署harbor私有镜像库(3)

    一.harbor介绍 在实际生产运维中,往往需要把镜像发布到几十.上百台或更多的节点上.这时单台Docker主机上镜像已无法满足,项目越来越多,镜像就越来越多,都放到一台Docker主机上是不行的,我 ...

  6. python基础之面向对象(一)(概念、实例、魔法方法)

    一.面向对象概念理解 1.面向对象和面向过程 面向过程:核心过程二字,过程即解决问题的步骤,就是先干什么后干什么 基于该思想写程序就好比在这是一条流水线,是一种机械式的思维方式 优点:复杂的过程流程化 ...

  7. origin2018去掉demo水印

    消除demo字样 有的origin破解完成后,使用没问题,但导出的图有demo水印.其实不需要重装,只需要下载一个补丁即可解决. 1. 把下载到的origin.exe复制到安装文件夹 2. 双击执行一 ...

  8. Docker的镜像理解以及容器的备份、恢复和迁移操作

    Docker的镜像理解以及容器的备份.恢复和迁移操作 这篇文章主要介绍了Docker的镜像理解以及容器的备份.恢复和迁移操作,覆盖很多原理知识以及容器的重要操作步骤,极力推荐!需要的朋友可以参考下 D ...

  9. 大数据学习之路—环境配置——IP设置(虚拟机修改Ip的内在原因及实现)

    一.IP原理 关于IP我的理解, (1)主要去理解IP地址的作用,IP地址包括网络相关部分和主机的相关部分.即:用一段特殊的数据,来标识网络特征和主机的特征. 至于具体的技术实现,日后可以慢慢体会和了 ...

  10. Python小白的数学建模课-03.线性规划

    线性规划是很多数模培训讲的第一个算法,算法很简单,思想很深刻. 要通过线性规划问题,理解如何学习数学建模.如何选择编程算法. 『Python小白的数学建模课 @ Youcans』带你从数模小白成为国赛 ...