Java中导出CSV格式文件至客户端及防止乱码情况

由于Csv格式简单,占内存少,生成的文件相对Excel小,可用各种编辑器打开等优点,导出类需求多用Csv格式

经测试导出10列40W行数据大小的表格大小约80M,若有更大数据量级可考虑写成压缩文件进行下载

导出时,数据中可能会出现一些数字过长的数据,导出后使用Excel打开会将数字科学计数法。出现这种情况我可以在该数据字段的后面加上制表符"\t" 注意不是:’\t’

Action代码如下:

@RequestMapping(value = "/export")
    public void getSkuList1(HttpServletResponse response,HttpServletRequest request){
    	        String[] arr = {"id","姓名","年龄"};
		List<String> cellList = new ArrayList<>();
		cellList.add("1,小明,13");
		cellList.add("2,小强,14");
		cellList.add("3,小红,15");
		String fileName = "导出文件.csv";
		// 生成CSV文件写入客户端
		ExcelUtils.createCSVFile(arr,cellList, fileName, response,request);
    }

maven依赖jar包:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-csv</artifactId>
    <version>1.8</version>
</dependency>

导出工具类:

import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVPrinter;

public class ExportCSVUtil {

    private static final Logger log = LoggerFactory.getLogger(ExportCSVUtil.class);

/**
     * CSV文件生成方法
     * @param head  表头
     * @param dataList  表数据
     * @param filename  文件名
     * @param response
     * @param request
     * @return
     */
    public static boolean createCSVFile(String[] head, List<String[]> dataList, String fileName,HttpServletResponse 
                                                                response,HttpServletRequest request) {
    	
    	byte[] bytes = new byte[0];
    	ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(byteArrayOutputStream, StandardCharsets.UTF_8);
	    BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);
	    CSVPrinter  csvPrinter = null;
	    
    	try {
    		if(dataList != null && dataList.size()>0){
    			
    			//创建csvPrinter并设置表格头
    			csvPrinter = new CSVPrinter(bufferedWriter, CSVFormat.DEFAULT.withHeader(head));
    			//写数据
    			csvPrinter.printRecords(dataList);
    			csvPrinter.flush();
    			bytes = byteArrayOutputStream.toString(StandardCharsets.UTF_8.name()).getBytes();
    					
        	}else{
        		log.error("当前数据为空,不能导出数据");
    			return false;
        	}
		} catch (Exception e) {
			
			log.error("导出excel过程中发生异常:"+e.getMessage(),e);
			return false;
			
		}finally {
			try {
				if (csvPrinter != null) {
					csvPrinter.close();
				}
				if (bufferedWriter != null) {
					bufferedWriter.close();
				}
				if (outputStreamWriter != null) {
					outputStreamWriter.close();
				}
				if (byteArrayOutputStream != null) {
					byteArrayOutputStream.close();
				}
			} catch (IOException e) {
				log.error("iostream close IOException:{}"+e.getMessage(), e);
				return false;
			}
		}
    	
    	if(bytes != null && bytes.length>0){
    		try {
    			//文件下载 不同浏览器对中文文件名处理方式不同
    	        if (request.getHeader("User-Agent").toUpperCase().indexOf("MSIE") > 0) {  
    	        	fileName = URLEncoder.encode(fileName, "UTF-8");  
    	        } else {  
    	        	fileName = new String(fileName.getBytes("UTF-8"), "ISO8859-1");  
    	        }
    			
    	        response.reset();//清空缓存数据
    	        response.setCharacterEncoding("UTF-8");
    	        response.setContentType("application/csv"); 
    	        response.addHeader("content-disposition", "attachment; filename=\"" + fileName+ "\"");
    			OutputStream outputStream = response.getOutputStream();
                        //这一行很重要!!! 是防止导出的CSV文件乱码
    			outputStream.write(new   byte []{( byte ) 0xEF ,( byte ) 0xBB ,( byte ) 0xBF });
    			outputStream.write(bytes);
    			outputStream.flush();
    		} catch (IOException e) {
    			log.error("iostream error:{}"+e.getMessage(), e);
    		}
    	}else{
    		log.error("当前数据为空,不能导出数据");
			return false;
    	}
    	return true;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值