使用Apache 的 commons-csv 實現 CSV 文件導出

1. CSV 簡介

CSV全稱是:Comma Separated Values (逗號分隔值)或者 Character Separated Values(字符分隔值)。其文件以純文本形式存儲表格數據(數字和文本)。CSV文件由任意數目的記錄組成,記錄間以某種換行符分隔;每條記錄由字段組成,字段間的分隔符是其它字符或字符串,最多見的是逗號或製表符。每一行記錄位於一個單獨的行上,用回車換行符CRLF(也就是\r\n)分割。apache

  • 對於excel來講默認使用 ,進行分割數據。編輯器

  • 每一行記錄最後一個字段後不能跟逗號編碼

  • 每一行一條記錄.net

  • 列爲空須要指定 ""3d

  • 用回車換行符CRLF(\r\n)分割每條記錄excel

  • 純文本,使用某個字符集,好比ASCII、Unicode、EBCDIC或GB2312code

2. 實現 CSV 文件導出

採用 Apache 開源的 commons-csv 包,詳細內容參考 官網orm

2.1 使用

2.1.1 引入依賴
<dependency>  
    <groupId>org.apache.commons</groupId>  
    <artifactId>commons-csv</artifactId>  
    <version>1.7</version>  
</dependency>
2.1.2 API
  1. print(Object value); // 寫入一個單元格數據
  1. printRecord(Iterable<?> values); // 寫入一行數據
  1. printRecords(Iterable<?> values);// 寫入多行數據

其餘重載方法⬇️blog

2.2 封裝一個導出方法

/**  
 * 導出 csv 文件  
 * [@param](https://my.oschina.net/u/2303379) out 輸出流  
 * [@param](https://my.oschina.net/u/2303379)  iter 數據 我這裏傳 List<List<Object>>   類型
 * [@param](https://my.oschina.net/u/2303379) charset 字符集編碼  
 * [@param](https://my.oschina.net/u/2303379)  header 表頭  
 */  
public void exportCSVFile(OutputStream out, Iterable<?> iter, String charset, String... header) {  
	  try {  
		  // 寫入bom, 防止中文亂碼  
		  byte[] bytes = {(byte) 0xEF, (byte) 0xBB, (byte) 0xBF};  
		  out.write(bytes);  

		  OutputStreamWriter osw = new OutputStreamWriter(out, charset);  
		  CSVFormat csvFormat = CSVFormat.EXCEL.withHeader(header);  

		  CSVPrinter csvPrinter = new CSVPrinter(osw, csvFormat);  
		  csvPrinter.printRecords(iter);  
		  csvPrinter.flush();  
		  csvPrinter.close();  
	  } catch (IOException e) {  
		  e.printStackTrace();  
	  }  
}

2.3 使用示例

List<List<Object>> lists = new ArrayList<>();  
​  
List<Object> list1 = new ArrayList<>();  
list1.add("張三");  
list1.add(18);  
list1.add("男");  
lists.add(list1);  
​  
List<Object> list2 = new ArrayList<>();  
list2.add("李四");  
list2.add(20);  
list2.add("女");  
lists.add(list2);  

String[] header = {"姓名", "年齡", "性別"};  

// 省略 out  

exportCSVFile(out, lists, "UTF-8", header);
  • Excel 打開

  • 文本編輯器打開字符串

    張三,18,男

    李四,20,女

2.4 可能遇到的問題

  • 使用 Excel 打開出現中文亂碼

    上面的示例代碼採用的是寫入 bom ,編碼爲 UTF-8 的方式解決的,也有其餘方案是使用編碼爲 GBK。

  • 用 Excel 打開後,日期格式會變成 ### 或者 2019/01/01 以及較大數字會變成科學技術法

    寫數據時加上製表符,一個製表符不夠,就 2 個
    不要調用 printRecords(); 方法,而是經過遍歷數據調用 csvPrinter.print("\t"+ 數據 +"\t");

    public void exportCSVFile(OutputStream out, Iterable<?> iter, String charset,String... header) {  
    	  try {  
    		  // 寫入bom, 防止中文亂碼  
    		  byte[] bytes = {(byte) 0xEF, (byte) 0xBB, (byte) 0xBF};  
    		  out.write(bytes);  
    
    		  OutputStreamWriter osw = new OutputStreamWriter(out, charset);  
    		  CSVFormat csvFormat = CSVFormat.EXCEL.withHeader(header);  
    
    		  CSVPrinter csvPrinter = new CSVPrinter(osw, csvFormat);  
    		  Iterator<?> iterator = iter.iterator();  
    		  while (iterator.hasNext()) {  
    			  Collection list = (Collection)iterator.next();  
    			  // 開始寫一行數據  
    			  list.forEach(c->{  
    				  try {  
    					  csvPrinter.print("\t" +c.toString() +"\t" );  
    				  } catch (IOException e) {  
    					  e.printStackTrace();  
    				  }  
    			  });  
    			  // 寫完一行,須要換行  
    			  csvPrinter.println();  
    		  }  
    		  csvPrinter.flush();  
    		  csvPrinter.close();  
    	  } catch (IOException e) {  
    		  e.printStackTrace();  
    	  }  
    }

注意: 添加了製表符以後,用文本編輯器打開後,格式就會變得很難看, 以下圖所示:

  • 寫入的數據包含逗號,雙引號等特殊字符時,導出的 csv 文件用文本編輯器打開,數據會用雙引號包裹起來, 以下所示:

  • 經過 Excel 修改 CSV 文件會出現兼容性問題

相關文章
相關標籤/搜索