用于读取和写入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);