前言
公司最近開發需要將數據保存到.csv文件(逗號分隔值 文件)中然后上傳到ftp服務器上,供我們系統還有客戶系統調用,之前完全沒有接觸過這個,所以先來看看百度的解釋:逗號分隔值(Comma-Separated Values,CSV,有時也稱為字符分隔值,因為分隔字符也可以不是逗號),其文件以純文本形式存儲表格數據(數字和文本)。純文本意味着該文件是一個字符序列,不含必須像二進制數字那樣被解讀的數據。CSV文件由任意數目的記錄組成,記錄間以某種換行符分隔;每條記錄由字段組成,字段間的分隔符是其它字符或字符串,最常見的是逗號或制表符。通常,所有記錄都有完全相同的字段序列。
CSV文件格式的通用標准並不存在,但是在RFC 4180中有基礎性的描述。使用的字符編碼同樣沒有被指定,但是7-bitASCII是最基本的通用編碼。
簡單的說就是逗號隔開 雙引號 內即為嗎需要的值 數據格式並沒有非常統一的標准 但是為了避免出錯 我們在開發的時候統一格式是這樣的
"name","pwd","date"
"張三","123","2015-09-30"
接下來代碼處理中默認格式都是這樣的 其實就是純文本的形式
為什么要用csv文件
這就涉及到數據互通的問題,有些程序支持的表格數據另一些程序並不見得支持,而csv格式的卻被大多數的應用程序支持,所以在交換保存數據的時候是個不錯的選擇。
而在項目開發中 有需要做的處理也不是很簡單的
比如有csv文件的讀取 數據的轉換(如轉成datatable),csv文件的重命名 ,csv文件的寫入,文件上傳到ftp服務器上等等
這里將開發的方法進行了簡單的整理,以備不時之需,時間倉促,有不足之處大家多多指點。
注意的點
①文件處理完的時候一定記得關閉釋放數據流 否則文件會被占用
②csv並沒有嚴格的標准,多人開發的時候必須規定好格式,統一開發
③文件末尾不能出現空的行,不然會出現datatable溢出情況,這種情況可以代碼處理 但是開發中最好約束好方便數據處理
一、將CSV文件的數據讀取到DataTable中
首先,我們為了方便管理,在web網站中常常需要讀取csv文件中的數據並且顯示在網站上方便查詢。所以比較方便的辦法是見csv文件中的數據轉換成datatable形式,代碼如下。
/// <summary> /// 將CSV文件的數據讀取到DataTable中 /// </summary> /// <param name="fileName">CSV文件路徑</param> /// <returns>返回讀取了CSV數據的DataTable</returns> public static DataTable OpenCSV(string filePath) { DataTable dt = new DataTable(); FileStream fs = new FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read); StreamReader sr = new StreamReader(fs, Encoding.UTF8); //StreamReader sr = new StreamReader(fs, encoding); //string fileContent = sr.ReadToEnd(); //記錄每次讀取的一行記錄 string strLine = ""; //記錄每行記錄中的各字段內容 string[] aryLine = null; string[] tableHead = null; //標示列數 int columnCount = 0; //標示是否是讀取的第一行 bool IsFirst = true; //逐行讀取CSV中的數據 while ((strLine = sr.ReadLine()) != null) { if (IsFirst == true) { tableHead = strLine.Split(','); IsFirst = false; columnCount = tableHead.Length; //創建列 for (int i = 0; i < columnCount; i++) { tableHead[i] = tableHead[i].Replace("\"", ""); DataColumn dc = new DataColumn(tableHead[i]); dt.Columns.Add(dc); } } else { aryLine = strLine.Split(','); DataRow dr = dt.NewRow(); for (int j = 0; j < columnCount; j++) { dr[j] = aryLine[j].Replace("\"",""); } dt.Rows.Add(dr); } } if (aryLine != null && aryLine.Length > 0) { dt.DefaultView.Sort = tableHead[2] + " " + "DESC"; } sr.Close(); fs.Close(); return dt; }
二、將DataTable中數據寫入到CSV文件中
當然我們一個文件中的數據遷移到另一個文件中或者 直接從數據庫中查詢的數據 插入到csv文件中 ,有一種方法是通過datatable的形式中轉,所以 需要把datatable 轉成 csv 代碼如下:
/// <summary> /// 將DataTable中數據寫入到CSV文件中 /// </summary> /// <param name="dt">提供保存數據的DataTable</param> /// <param name="fileName">CSV的文件路徑</param> public static bool SaveCSV(DataTable dt, string fullPath) { try { FileInfo fi = new FileInfo(fullPath); if (!fi.Directory.Exists) { fi.Directory.Create(); } FileStream fs = new FileStream(fullPath, System.IO.FileMode.Create, System.IO.FileAccess.Write); //StreamWriter sw = new StreamWriter(fs, System.Text.Encoding.Default); StreamWriter sw = new StreamWriter(fs, System.Text.Encoding.UTF8); string data = ""; //寫出列名稱 for (int i = 0; i < dt.Columns.Count; i++) { data += "\"" + dt.Columns[i].ColumnName.ToString() + "\""; if (i < dt.Columns.Count - 1) { data += ","; } } sw.WriteLine(data); //寫出各行數據 for (int i = 0; i < dt.Rows.Count; i++) { data = ""; for (int j = 0; j < dt.Columns.Count; j++) { string str = dt.Rows[i][j].ToString(); str = string.Format("\"{0}\"", str); data += str; if (j < dt.Columns.Count - 1) { data += ","; } } sw.WriteLine(data); } sw.Close(); fs.Close(); return true; } catch { return false; } }
三、修改文件名稱
修改文件名稱 我們需要保存歷史數據 或者實時的知道那個文件被修改 可以通過改變文件的名稱 如加上當天的日期等等 方便管理
/// <summary> /// 修改文件名稱 /// </summary> /// <param name="OldPath">舊的路徑 完整的物理路徑</param> /// <param name="NewPath">新的路徑</param> /// <returns></returns> public static bool ChangeFileName(string OldPath, string NewPath) { bool re = false; //OldPath = HttpContext.Current.Server.MapPath(OldPath);虛擬的 //NewPath = HttpContext.Current.Server.MapPath(NewPath); try { if (File.Exists(OldPath)) { File.Move(OldPath, NewPath); re = true; } } catch { re = false; } return re; }
四、scv文件的數據寫入
直接在網頁表單提交數據保存在csv文件中 直接寫入文件
1 /// <summary> 2 /// 寫入文件 3 /// </summary> 4 /// <param name="fullPath"></param> 5 /// <param name="Data"></param> 6 /// <returns></returns> 7 public static bool SaveCSV(string fullPath,string Data) 8 { 9 bool re = true; 10 try 11 { 12 FileStream FileStream = new FileStream(fullPath, FileMode.Append); 13 StreamWriter sw = new StreamWriter(FileStream, System.Text.Encoding.UTF8); 14 sw.WriteLine(Data); 15 //清空緩沖區 16 sw.Flush(); 17 //關閉流 18 sw.Close(); 19 FileStream.Close(); 20 } 21 catch { 22 re = false; 23 } 24 return re; 25 }
五、上傳到ftp服務器
把處理好的數據文件上傳到ftp服務器供系統調用
/// <summary> /// 上傳文件 /// </summary> /// <param name="fileinfo">需要上傳的文件</param> /// <param name="targetDir">目標路徑</param> /// <param name="hostname">ftp地址(不帶ftp;//)</param> /// <param name="username">ftp用戶名</param> /// <param name="password">ftp密碼</param> public static bool UploadFtpFile(FileInfo fileinfo, string targetDir, string hostname, string username, string password) { bool re = true; //1. check target string target; if (targetDir.Trim() == "") { return false; } target = fileinfo.Name; //使用臨時文件名 string URI = "FTP://" + hostname + "/" + targetDir + "/" + target; ///WebClient webcl = new WebClient(); System.Net.FtpWebRequest ftp = GetRequest(URI, username, password); //設置FTP命令 設置所要執行的FTP命令, //ftp.Method = System.Net.WebRequestMethods.Ftp.ListDirectoryDetails;//假設此處為顯示指定路徑下的文件列表 ftp.Method = System.Net.WebRequestMethods.Ftp.UploadFile; //指定文件傳輸的數據類型 ftp.UseBinary = true; ftp.UsePassive = true; //告訴ftp文件大小 ftp.ContentLength = fileinfo.Length; //緩沖大小設置為2KB const int BufferSize = 2048; byte[] content = new byte[BufferSize - 1 + 1]; int dataRead; //打開一個文件流 (System.IO.FileStream) 去讀上傳的文件 using (FileStream fs = fileinfo.OpenRead()) { try { //把上傳的文件寫入流 using (Stream rs = ftp.GetRequestStream()) { do { //每次讀文件流的2KB dataRead = fs.Read(content, 0, BufferSize); rs.Write(content, 0, dataRead); } while (!(dataRead < BufferSize)); rs.Close(); } } catch (Exception ex) { re = false; } finally { fs.Close(); } } return re; }
本文版權歸作者(謝俊)和博客園所有,歡迎轉載,轉載請標明出處。
原文地址:http://www.cnblogs.com/net-xiejun/
完整源碼下載:https://github.com/xiejun-net/weixin
公眾賬號: