逗號分隔值(Comma-Separated Values,CSV,有時也稱為字元分隔值,因為分隔字元也可以不是逗號),其檔案以純文字形式儲存表格資料(數字和文字)。純文字意味著該檔案是一個字元序列,不含必須像二進位數字那樣被解讀的資料。CSV檔案由任意數目的記錄組成,記錄間以某種換行符分隔;每條記錄由欄位組成,欄位間的分隔符是其它字元或字串,最常見的是逗號或制表符。通常,所有記錄都有完全相同的欄位序列。
CSV檔案的格式不存在通用標準,也沒有指定所使用的字元編碼
這就讓我吃了點小苦頭, 原先從專案搬運回PD的程式
輸出的csv是
"ABC","DEF".....
這樣的格式
其目的很簡單就是為了要避免欄位之中有, 或 " 的問題
但是我們偉大的Microsoft Excel 輸出卻是
ABC,DEF
於是考慮到User使用excel 操作之後, 格式會改變
因此我研究了一下,在Ms Excel 標準之下的csv檔輸出格式
[案例]
~ ! @ # $ %
^ & * ( ) _
+ ` - = [ ]
; ' , . / <
> ? : " { }
從以上的列表中可以發現,需要處理的char有 , 跟 "
規則其實很簡單
就是當某格欄位裡有,或" 時
則該格會用用""將字串包起來,並且把字串裡的"換成""
EX:
, => ","
" => """" (一個" 等於兩個" 再用"" 包起來.
"" => """"""
有了以上的規則
我們可以很簡單的做出這樣的匯出方法
/// /// 產生內容 /// /// public string GetContent() { string[] dataSort = GetContentArray(); return string.Join(",", dataSort.Select(s => fixCSVSpecisalChar(s))); } private string fixCSVSpecisalChar(string str) { if (str.Contains(@",") || str.Contains(@"""")) { str = @"""" + str.Replace(@"""", @"""""") + @""""; } return str; }
再來說到匯入
就比較麻煩了
因為如果用split(',')
會不好處理類似這樣的案例
EX:
ABC,"a,",""",""b",DEF所以我們不要重複造輪子
直接找前人寫的framework使用
首先找到了第一個方案
LumenWorks.Framework.IO
使用visual studio 開發時, 他可以很簡單的從nuget安裝
安裝之後的使用方式也是很簡單,以下是sample
using (var csvReader = new CsvReader(new StreamReader(file.InputStream, System.Text.Encoding.Default))) { //讀取第一行字當作Title. var titleLine = csvReader.GetFieldHeaders(); //依序移動到下一行 while (csvReader.ReadNextRecord()) { var array = new string[csvReader.Columns.Count]; csvReader.CopyCurrentRecordTo(array, 0); } }
後來考慮到授權問題,以及其實本部門有購買不便宜的Aspose ,當然就要用好用滿
以下是Aspose的sample
using Aspose.Cells; public static IList<string[]> LoadCSV(Stream fileStream, System.Text.Encoding encoding) { TxtLoadOptions loadOptions = new TxtLoadOptions(LoadFormat.CSV); loadOptions.ConvertNumericData = false; loadOptions.Encoding = encoding; IList<string[]> rs = new List<string[]>(); using (var workbook = new Workbook(fileStream, loadOptions)) { Worksheet sheet = workbook.Worksheets[0]; object[,] dataArray = sheet.Cells.ExportArray(0, 0, sheet.Cells.MaxDataRow + 1, sheet.Cells.MaxDataColumn + 1); for (int i = 0; i <= dataArray.GetLength(0) - 1; i++) { List<string> cell = new List<string>(); for (int j = 0; j <= dataArray.GetLength(1) - 1; j++) { cell.Add(Convert.ToString(dataArray[i, j])); } rs.Add(cell.ToArray()); } } return rs; }
var csv = ExcelHandler.LoadCSV(file.InputStream, System.Text.Encoding.Default); var titleLine = csv.First(); foreach (var array in csv) { if (titleIndex == 0) { titleIndex++; continue; } }