使用 CsvHelper 的讀寫操作在前兩篇都已經有說明了,如果需要更進階的操作說明,可以直接參考 CsvHelper 的文件檔或是直接到 Github Repository 裡面的單元測試專案裡去看,而這一篇則是再補上一些在處理 CSV 檔案讀寫時的方法操作說明。
使用 CsvHelper - Part.1 資料寫入
使用 CsvHelper - Part.2 資料讀取
Github - CsvHelper
https://github.com/JoshClose/CsvHelper
CsvHelper Documentation
http://joshclose.github.io/CsvHelper/
判斷 CSV 檔案是否存在以及是否有資料
判斷檔案是否存在,這只需要使用到 System.IO File 的 Exists 方法做處裡就可以,而如果檔案存在則要去判斷檔案內是否有資料,有些人的做法是先將 CSV 檔案的全部資料讀取之後再去做判斷,這個做法很直接,但如果碰到資料很多的時候,這方法就不是很好。
例如使用 CsvHelper 時,有些人會用以下的方式去判斷是否有資料的存在,先把 CSV 裡的全部資料取出來之後再去判斷是不是有資料,這方法當遇到 CSV 檔案裡有很多資料再加上有頻繁讀寫的狀況時,這做法就不是很適當,
可以改用以下的做法,一開始先去判斷檔案是否存在,如果檔案存在才去使用 CsvHelper 讀取檔案,這邊會使用到 CsvReader 的 IsRecordEmpty 方法,不過用這方法前要先執行 CsvReader 的 Read 方法,要先讓 CsvReader 讀檔案,這樣才能判斷 CSV 檔案內是否有資料,而單純的讀檔案而並沒有去「取出」檔案內的資料,這在效能上就會有很大的差別。
使用 Append 方式讓資料接續寫入 CSV 檔案
在第一篇介紹使用 CsvHelper 處理資料寫入的時候都是以查詢出來的全部資料寫入到 CSV 檔案裡,但如果是要將一筆資料接續在 CSV 檔案的最後面的話,這應該怎麼處理呢?
例如,我們已經將一筆資料寫入到 Foobar.csv 檔案裡,
如果是想用 CsvReader 的 WriteRecord 方法將資料寫入到 CSV 檔案的話,就會得到以下的結果,
如果要接續寫入既有的 CSV 檔案,在一開始的 StreamWriter 就需要做設定,
MSDN- StreamWriter 類別 (System.IO)
MSDN - StreamWriter 建構函式 (String, Boolean, Encoding) (System.IO)
“使用指定的編碼方式和預設緩衝區大小,為指定的檔案初始化 StreamWriter 類別的新執行個體。 如果檔案存在,可以將它寫入或附加。 如果檔案不存在,這個建構函式會建立新的檔案。”
“append: true 表示要附加資料至檔案,false 表示要覆寫檔案。 如果指定的檔案不存在,則這個參數沒有任何作用,而且建構函式會建立新的檔案。”
所以這邊就將寫入資料到 CSV 檔案的程式做了修改,並且配合上面所建立的 IsNotExistOrRecordEmpty 方法,這是要去判斷是否有無資料,如果沒有資料就需要在 CSV 的第一列寫入欄位名稱,如果已經資料存在就不需要去寫入欄位名稱。
public void WriteToCSV<T>(string file, T record)
{
bool isNotExistsOrRecordEmpty = IsNotExistsOrRecordEmpty(file);
using (var sw = new StreamWriter(file, true, Encoding.UTF8))
using (var writer = new CsvWriter(sw))
{
if(isExistsOrRecordEmpty)
{
writer.WriteHeader(typeof(T));
}
writer.WriteRecord(record);
}
}
public bool IsNotExistsOrRecordEmpty(string file)
{
if(!File.Exists(file))
{
return true;
}
using (var sr = new StreamReader(file))
using (var reader = new CsvReader(sr))
{
reader.Read();
return reader.IsRecordEmpty();
}
}
使用方式
輸出結果
將要輸入的資料內容做個修改然後再執行一次,
重新整理程式,完整的程式內容如下:
void Main()
{
string fileName = @"z:\Foobar.csv";
var record = new Foobar()
{
ID = "111",
FirstName = "222",
LastName = "333",
Title = "444"
};
WriteToCSV<Foobar>(fileName, record);
var records = ReadFromCSV<Foobar>(fileName);
records.Dump();
}
public IEnumerable<T> ReadFromCSV<T>(string file)
{
using (var sr = new StreamReader(file))
using (var reader = new CsvReader(sr))
{
var records = reader.GetRecords<T>();
return records.ToList();
}
}
public void WriteToCSV<T>(string file, T record)
{
bool isNotExistsOrRecordEmpty = IsNotExistsOrRecordEmpty(file);
using (var sw = new StreamWriter(file, true, Encoding.UTF8))
using (var writer = new CsvWriter(sw))
{
if(isNotExistsOrRecordEmpty)
{
writer.WriteHeader(typeof(T));
}
writer.WriteRecord(record);
}
}
public bool IsNotExistsOrRecordEmpty(string file)
{
if(!File.Exists(file))
{
return true;
}
using (var sr = new StreamReader(file))
using (var reader = new CsvReader(sr))
{
reader.Read();
return reader.IsRecordEmpty();
}
}
public class Foobar
{
public string ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Title { get; set; }
}
以上
沒有留言:
張貼留言