用於讀取和寫入CSV文件的.NET庫。 很是快速,靈活和易於使用。 支持讀寫自定義類對象。git
要安裝CsvHelper,請從包管理器控制檯運行如下操做。github
Install-Package CsvHelper
閱讀全部記錄很簡單。 若是有一個的類結構的鏡像CSV文件,能夠將整個文件讀入。數組
var csv = new CsvReader( textReader ); var records = csv.GetRecords<MyClass>();
若是要自定義CSV文件映射到自定義類對象的方式,可使用映射。(後面將會介紹)app
返回的IEnumerable <T>將產生結果。 這意味着在實際訪問數據以前不會返回結果。 由於整個文件將不會被加載到內存中,而且當您訪問數據時,該文件將被讀取。 若是您須要屢次迭代記錄(例如使用Count),則能夠將全部內容加載到列表和數據的工做中。ide
var csv = new CsvReader( textReader ); var records = csv.GetRecords<MyClass>().ToList();
能夠循環行並逐條讀取它們。spa
var csv = new CsvReader( textReader ); while( csv.Read() ) { var record = csv.GetRecord<MyClass>(); }
也能夠逐項讀取每一個字段。code
var csv = new CsvReader( textReader ); while( csv.Read() ) { var intField = csv.GetField<int>( 0 ); var stringField = csv.GetField<string>( 1 ); var boolField = csv.GetField<bool>( "HeaderName" ); }
若是你可能獲得字段的類型有不一致的地方,你能夠用trygetfield。orm
var csv = new CsvReader( textReader ); while( csv.Read() ) { int intField; if( !csv.TryGetField( 0, out intField ) ) { // Do something when it can't convert. } }
您還能夠直接使用分析器而不使用讀取器。分析器將爲讀取的每一行返回一個字符串數組,當它完成時將返回null。 對象
var parser = new CsvParser( textReader ); while( true ) { var row = parser.Read(); if( row == null ) { break; } }
若是你想有一個類結構鏡像的CSV文件,你能夠直接寫整個文件。blog
var csv = new CsvWriter( textWriter ); csv.WriteRecords( records );
您能夠循環對象並逐條編寫它們。
var csv = new CsvWriter( textWriter ); foreach( var item in list ) { csv.WriteRecord( item ); }
也能夠逐項寫每一個字段。
var csv = new CsvWriter( textWriter ); foreach( var item in list ) { csv.WriteField( "a" ); csv.WriteField( 2 ); csv.WriteField( true ); csv.NextRecord(); }
若是不提供映射文件,將使用自動映射。 自動映射將按照它們顯示的順序映射類中的屬性。若是屬性是一個自定義類,它會按照它們顯示的順序遞歸地的屬性類映射。若是自動映射器命中循環引用,那麼它將 中止映射.
若是您的CSV文件與自定義類不匹配,您可使用一個類映射來設置類如何映射到文件的列。您須要在配置中註冊您的類映射。
public sealed class MyClassMap : CsvClassMap<MyClass> { public MyClassMap() { Map( m => m.Id ); Map( m = > m.Name ); } }
引用地圖用於將自定義類的屬性,將其映射到幾個CSV列。您能夠嵌套參考圖的許多層深,只要你喜歡。
public sealed class PersonMap : CsvClassMap<Person> { public PersonMap() { Map( m => m.Id ); Map( m => m.Name ); References<AddressMap>( m => m.Address ); } } public sealed class AddressMap : CsvClassMap<Address> { public AddressMap() { Map( m => m.Street ); Map( m => m.City ); Map( m => m.State ); Map( m => m.Zip ); } }
當經過索引映射時,您指定要爲該屬性使用的CSV列的索引。
public sealed class MyClassMap : CsvClassMap<MyClass> { public MyClassMap() { Map( m => m.Id ).Index( 0 ); Map( m => m.Name ).Index( 1 ); } }
按列名映射時,指定要爲該屬性使用的CSV列的名稱。要工做,CSV文件必須有頭記錄。指定的名稱必須與頭記錄的名稱匹配。
public sealed class MyClassMap : CsvClassMap<MyClass> { public MyClassMap() { Map( m => m.Id ).Name( "The Id Column" ); Map( m => m.Name ).Name( "The Name Column" ); } }
有時CSV文件有多個名稱相同的列。 發生這種狀況時,可使用NameIndex來指定您所指的列名。 NameIndex不是CSV文件中的列,而是同名列的索引。
public sealed class MyClassMap : CsvClassMap<MyClass> { public MyClassMap() { Map( m => m.FirstName ).Name( "Name" ).NameIndex( 0 ); Map( m => m.LastName ).Name( "Name" ).NameIndex( 1 ); } }
若是字段爲空,默認值用於設置要使用的默認值。
public sealed class MyClassMap : CsvClassMap<MyClass> { public override void MyClassMap() { Map( m => m.Id ).Index( 0 ).Default( -1 ); Map( m => m.Name ).Index( 1 ).Default( "Unknown" ); } }
若是CSV字段的值不能被自動轉換爲屬性的類型,你能夠指定一個自定義csvhelper.typeconversion.itypeconverter用來轉換。有關如何建立自定義類型請看類型轉換器的文檔。
public sealed class MyClassMap : CsvClassMap<MyClass> { public MyClassMap() { Map( m => m.Id ).Index( 0 ).TypeConverter<MyIdConverter>(); } }
默認內置轉換器將處理大多數類型轉換的狀況,但有時也有一些小的變化,你想作,但不想建立一個完整的新型轉換器,只是一個int(例如)分析不一樣。您能夠指定一些類型轉換器選項來處理這些狀況。
public sealed class MyClassMap : CsvClassMap<MyClass> { public MyClassMap() { Map( m => m.Description ).Index( 0 ).TypeConverterOption( CultureInfo.InvariantCulture ); Map( m => m.TimeStamp ).Index( 1 ).TypeConverterOption( DateTimeStyles.AdjustToUniversal ); Map( m => m.Cost ).Index( 2 ).TypeConverterOption( NumberStyles.Currency ); Map( m => m.CurrencyFormat ).Index( 3 ).TypeConverterOption( "C" ); Map( m => m.BooleanValue ).Index( 4 ).TypeConverterOption( true, "sure" ).TypeConverterOption( false, "nope" ); } }
使用轉換
當一切都失敗了,你能夠用convertusing。convertusing容許您編寫自定義代碼內聯轉把行轉換成一個單一的屬性值。
public sealed class MyClassMap : CsvClassMap<MyClass> { public MyClassMap() { // Constant value. Map( m => m.Constant ).ConvertUsing( row => 3 ); // Aggregate of two rows. Map( m => m.Aggregate ).ConvertUsing( row => row.Get<int>( 0 ) + row.Get<int>( 1 ) ); // Collection with a single value. Map( m => m.Names ).ConvertUsing( row => new List<string>{ row.Get<string>( "Name" ) } ); // Just about anything. Map( m => m.Anything ).ConvertUsing( row => { // You can do anything you want in a block. // Just make sure to return the same type as the property. } ); } }
運行時映射
地圖能夠在運行時建立。事實上,自動地圖功能動態。你能夠看看下面的連接的一些啓示:https://github.com/JoshClose/CsvHelper/blob/master/src/CsvHelper/Configuration/CsvClassMap.cs#L91另外一個簡單的例子以下所示:
var customerMap = new DefaultCsvClassMap(); // mapping holds the Property - csv column mapping foreach( string key in mapping.Keys ) { var columnName = mapping[key].ToString(); if( !String.IsNullOrEmpty( columnName ) ) { var propertyInfo = typeof( Customer ).GetType().GetProperty( key ); var newMap = new CsvPropertyMap( propertyInfo ); newMap.Name( columnName ); customerMap.PropertyMaps.Add( newMap ); } } csv.Configuration.RegisterClassMap(CustomerMap);