ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Spring Boot下的一种导出CSV文件的代码框架

2021-06-19 20:01:46  阅读:92  来源: 互联网

标签:CsvExportable String Spring Boot item 导出 import CSV


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格式的数据。

标签:CsvExportable,String,Spring,Boot,item,导出,import,CSV
来源: https://www.cnblogs.com/alabo1999/p/14904731.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有