目錄:
為什麼要使用 CsvHelper? csv 格式看起來很簡單,就簡單寫一寫使用逗號區隔就好了,不過有個大家常常會忽略的小問題,就是內容中出現「,」時會和 csv 的分隔符號衝突,雖然可以自己將內容加上引號「"」,但是就要多寫各種判斷。而 CsvHelper 能夠快速、自動的將類別轉為 csv 格式輸出,省去徒手再造輪子的麻煩。
建立假資料
將 list 直接輸出成 csv 檔案
輸出的資料:
輸出的資料:
輸出的資料:
輸出的資料:
使用和上面相同的資料類別
讀取資料並顯示:
可以發現只要有標題的情況下順序不同也是能正常讀取的
讀取方式為:
但此時是依照目標類別的變數順序存放的,我們可以使用 Index 屬性(Index Attribute) 來自定各變數為 csv 檔案中的第幾個資料 (index 從 0 開始)
CsvHelper
介紹
什麼是 csv? csv 是在 RFC 4180 中描述的一種通用格式,全名是 Comma-Separated Values,逗號分隔值,是一種純文字的通用資料格式,能夠方便的用來傳輸表格資料。為什麼要使用 CsvHelper? csv 格式看起來很簡單,就簡單寫一寫使用逗號區隔就好了,不過有個大家常常會忽略的小問題,就是內容中出現「,」時會和 csv 的分隔符號衝突,雖然可以自己將內容加上引號「"」,但是就要多寫各種判斷。而 CsvHelper 能夠快速、自動的將類別轉為 csv 格式輸出,省去徒手再造輪子的麻煩。
安裝 CsvHelper
使用 NuGet 或是下面的 .NET CLI 指令安裝 CsvHelper
dotnet add package CsvHelper --version 28.0.1
輸出 csv 檔案
先建立輸出資料的類別
public class Entity
{
public int Id { get; set; }
public string Name { get; set; }
}
建立假資料
List<Entity> entities = new List<Entity>();
entities.Add(new Entity { Id = 1, Name = "Ruyut"});
entities.Add(new Entity { Id = 2, Name = "小明"});
將 list 直接輸出成 csv 檔案
using var writer = new StreamWriter("test.csv");
using var csv = new CsvWriter(writer, CultureInfo.InvariantCulture);
csv.WriteRecords((IEnumerable)entities);
輸出的資料:
Id,Name
1,Ruyut
2,小明
調整輸出內容的順序
透過在類別上面增加 Index 屬性(Index Attribute) 可以自訂輸出內容的順序(index 從 0 開始)
using CsvHelper.Configuration.Attributes;
public class Entity
{
[Index(1)] public int Id { get; set; }
[Index(0)] public string Name { get; set; }
}
輸出的資料:
Name,Id
Ruyut,1
小明,2
自訂標題名稱
透過在類別上面增加 Name 屬性(Name Attribute) 可以自訂輸出的標題名稱
using CsvHelper.Configuration.Attributes;
public class Entity
{
[Name("編號")] public int Id { get; set; }
[Name("名稱")] public string Name { get; set; }
}
輸出的資料:
編號,名稱
1,Ruyut
2,小明
輸出內容不包含標題
預設輸出的內容會有變數的名稱做標題,如果不想要第一行資料是標題,可以使用 CsvConfiguration 設定
var config = new CsvConfiguration(CultureInfo.InvariantCulture) { HasHeaderRecord = false };
using var writer = new StreamWriter("test.csv");
using var csv = new CsvWriter(writer, config);
csv.WriteRecords((IEnumerable)entities);
輸出的資料:
1,Ruyut
2,小明
輸出內容接續在原始內容後面
雖然是將內容接續在後面,但是還是會再次輸出標題,所以本次的範例為「接續先前文件且輸出內容不包含標題」
var config = new CsvConfiguration(CultureInfo.InvariantCulture) { HasHeaderRecord = false };
using var stream = File.Open("test.csv", FileMode.Append);
using var writer = new StreamWriter(stream);
using var csv = new CsvWriter(writer, config);
csv.WriteRecords((IEnumerable)entities);
讀取 csv 檔案
範例資料:
Name,Id
Ruyut,1
小明,2
使用和上面相同的資料類別
public class Entity
{
public int Id { get; set; }
public string Name { get; set; }
}
讀取資料並顯示:
using var reader = new StreamReader("test.csv");
using var csv = new CsvReader(reader, CultureInfo.InvariantCulture);
var records = csv.GetRecords<Entity>();
foreach (var record in records)
{
Console.WriteLine($"Id: {record.Id}, Name: {record.Name}");
// Id: 1, Name: Ruyut
// Id: 2, Name: 小明
}
可以發現只要有標題的情況下順序不同也是能正常讀取的
讀取標題和變數名稱不同的 csv 檔案
當 csv 檔案第一行資料和變數名稱命名不同時,我們可以透過在類別上面增加 Name 屬性(Name Attribute) 可以自訂讀取時該欄位資料放置的變數
using CsvHelper.Configuration.Attributes;
public class Entity
{
[Name("編號")] public int Id { get; set; }
[Name("名稱")] public string Name { get; set; }
}
讀取沒有標題的 csv 檔案
在讀取沒有標題的 csv 檔案時會拋出下列錯誤:
Unhandled exception. CsvHelper.HeaderValidationException: Header with name 'Id'[0] was not found.
讀取方式為:
using var reader = new StreamReader("test.csv");
var config = new CsvConfiguration(CultureInfo.InvariantCulture) { HasHeaderRecord = false };
using var csv = new CsvReader(reader, config);
var records = csv.GetRecords<Entity>();
但此時是依照目標類別的變數順序存放的,我們可以使用 Index 屬性(Index Attribute) 來自定各變數為 csv 檔案中的第幾個資料 (index 從 0 開始)
using CsvHelper.Configuration.Attributes;
namespace CsvHelperConsoleAppTest;
public class Entity
{
[Index(1)] public string Id { get; set; }
[Index(0)] public string Name { get; set; }
}
參考資料
CsvHelper
留言
張貼留言
如果有任何問題、建議、想說的話或文章題目推薦,都歡迎留言或來信: a@ruyut.com