This code is based on CsvHelper 15.0.5
Introduction to the
CsvHelper is a tool for reading and writing CSV files. The.net libraries. Extremely fast, flexible and easy to use.
CsvHelper is built on. On TOP of NET Standard 2.0, it can run almost anywhere.
Github address: github.com/joshclose/c…
The module
The module | function |
---|---|
CsvHelper | Core classes for reading and writing CSV data. |
CsvHelper.Configuration | Class that configures the read and write behavior of CsvHelper. |
CsvHelper.Configuration.Attributes | Configure CsvHelper features. |
CsvHelper.Expressions | Class that generates LINQ expressions. |
CsvHelper.TypeConversion | A class that converts CSV fields to and from.NET types. |
read
The test class
public class Foo
{
public int ID { get; set; }
public string Name { get; set; }}Copy the code
CSV file data
ID,Name
1,Tom
2,Jerry
Copy the code
Read all records
using (var reader = new StreamReader("foo.csv"))
{
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
varrecords = csv.GetRecords<Foo>(); }}Copy the code
Blank lines are ignored when reading the CSV file. If blank lines contain Spaces, an error is reported. If it is an Excel edited CSV file, empty lines will become lines containing only delimiters, and an error will be reported.
To read a detailed
using (var reader = new StreamReader("foo.csv"))
{
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
while (csv.Read())
{
varrecord = csv.GetRecord<Foo>(); }}}Copy the code
The GetRecords
method yields an IEnumerable
and does not read it all into memory at once unless ToList or ToArray methods are called. So there’s not a lot of need to do that.
Reading a single field
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
csv.Read();
csv.ReadHeader();
while (csv.Read())
{
var id = csv.GetField<int> (0);
var name = csv.GetField<string> ("Name"); }}Copy the code
When reading line by line, you can ignore the header line, but not here.
csv.Read(); The while loop gets the title for the first time, and if it doesn’t get the title for the first time, it’s going to get an error.
csv.ReadHeader(); Csv.getfield
(“Name”) does not find the title.
Use TryGetField to prevent unexpected errors.
csv.TryGetField(0.out int id);
Copy the code
write
Write all records
var records = new List<Foo>
{
new Foo { ID = 1, Name = "Tom" },
new Foo { ID = 2, Name = "Jerry"}};using (var writer = new StreamWriter("foo.csv"))
{
using (var csv = newCsvWriter(writer, CultureInfo.InvariantCulture)) { csv.WriteRecords(records); }}Copy the code
To write a detailed
using (var writer = new StreamWriter("foo.csv"))
{
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
{
foreach (var record inrecords) { csv.WriteRecord(record); }}}Copy the code
Field by field write
using (var writer = new StreamWriter("foo.csv"))
{
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
{
csv.WriteHeader<Foo>();
csv.NextRecord();
foreach (var record inrecords) { csv.WriteField(record.ID); csv.WriteField(record.Name); csv.NextRecord(); }}}Copy the code
features
Index
The Index feature marks the order of fields.
When you read a file, if there is no title, you can only determine the fields by order.
public class Foo
{
[Index(0)]
public int ID { get; set; }
[Index(1)]
public string Name { get; set; }}using (var reader = new StreamReader("foo.csv"))
{
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
csv.Configuration.HasHeaderRecord = false;
varrecords = csv.GetRecords<Foo>().ToList(); }}Copy the code
CSV. Configuration. HasHeaderRecord = false Configuration told CsvReader no title. This line must be added, otherwise the title of the first action will be skipped by default, resulting in a missing line in the final result. If there is a large amount of data, it will be difficult to find this bug.
Files are written in Index order. If you don’t want to write the title, also need to add the CSV Configuration. HasHeaderRecord = false;
Name
If the field Name and column Name do not match, the Name attribute can be used.
public class Foo
{
[Name("id")]
public int ID { get; set; }
[Name("name")]
public string Name { get; set; }}Copy the code
NameIndex
NameIndex is used to process the same names in CSV files.
public class Foo{... [Name("Name")]
[NameIndex(0)]
public string FirstName { get; set; }
[Name("Name")]
[NameIndex(1)]
public string LastName { get; set; }}Copy the code
Ignore
Ignore the field
Optional
If no matching field is found while reading, it is ignored.
public class Foo{... [Optional]public string Remarks { get; set; }}Copy the code
Default
The Default feature specifies a Default value for a field read when it is empty.
The Default feature is valid only when read. Null values are not replaced by Default values when written.
NullValues
public class Foo{... [NullValues("None"."none"."Null"."null")]
public string None { get; set; }}Copy the code
When the file is read, if the value of a field in the CSV file is null, the value is “” instead of null. After the NullValues feature is marked, if the value of a field in the CSV file is the specified value, the value is null.
If the Default feature is marked at the same time, it does not take effect.
Unfortunately, this feature does not work when writing files. This can cause read and write inconsistency problems.
Constant
The Constant feature specifies a Constant value for the field, which is used for reading and writing regardless of any other mapping or configuration specified.
Format
Format Specifies the string Format to be used for type conversion.
For example, we often specify the format of numeric and time types.
public class Foo{... [Format("0.00")]
public decimal Amount { get; set; }
[Format("yyyy-MM-dd HH:mm:ss")]
public DateTime JoinTime { get; set; }}Copy the code
BooleanTrueValues and BooleanFalseValues
These two features are used to convert bool to display in the specified form.
public class Foo{... [BooleanTrueValues("yes")]
[BooleanFalseValues("no")]
public bool Vip { get; set; }}Copy the code
NumberStyles
public class Foo{... [Format("X2")]
[NumberStyles(NumberStyles.HexNumber)]
public int Data { get; set; }}Copy the code
Useful is NumberStyles HexNumber and NumberStyles AllowHexSpecifier, the role of the two enumeration. This feature is valid only when read, and does not convert to hexadecimal writes when written. This can lead to inconsistent reads and writes, and you can use the Format feature to specify the write Format.
mapping
If you cannot add features to the classes you want to map, in this case you can use the ClassMap approach.
The effect of using maps is the same as that of using features. The following example implements the functionality of the above feature using properties.
public class Foo2 { public int ID { get; set; } public string Name { get; set; } public decimal Amount { get; set; } public DateTime JoinTime { get; set; } public string Msg { get; set; } public string Msg2 { get; set; } public bool Vip { get; set; } public string Remarks { get; set; } public string None { get; set; } public int Data { get; set; } } public class Foo2Map : ClassMap<Foo2> { public Foo2Map() { Map(m => m.ID).Index(0).Name("id"); Map(m => m.Name).Index(1).Name("name"); The Map (m = > m. mount). TypeConverterOption. The Format (" 0.00 "); Map(m => m.JoinTime).TypeConverterOption.Format("yyyy-MM-dd HH:mm:ss"); Map(m => m.Msg).Default("Hello"); Map(m => m.Msg2).Ignore(); Map(m => m.Vip) .TypeConverterOption.BooleanValues(true, true, new string[] { "yes" }) .TypeConverterOption.BooleanValues(false, true, new string[] { "no" }); Map(m => m.Remarks).Optional(); Map(m => m.None).TypeConverterOption.NullValues("None", "none", "Null", "null"); Map(m => m.Data) .TypeConverterOption.NumberStyles(NumberStyles.HexNumber) .TypeConverterOption.Format("X2"); }}Copy the code
You need to register a map before using it
csv.Configuration.RegisterClassMap<Foo2Map>();
Copy the code
ConvertUsing
ConvertUsing allows type conversions to be implemented using a delegate method.
/ / constant
Map(m => m.Constant).ConvertUsing(row => 3);
// aggregate the two columns together
Map(m => m.Name).ConvertUsing(row => $"{row.GetField<string> ("FirstName")} {row.GetField<string> ("LastName")}");
Map(m => m.Names).ConvertUsing(row => new List<string> { row.GetField<string> ("Name")});Copy the code
configuration
Delimiter
The separator
csv.Configuration.Delimiter = ",";
Copy the code
HasHeaderRecord
This configuration was mentioned earlier whether to use the first line as the title
csv.Configuration.HasHeaderRecord = false;
Copy the code
IgnoreBlankLines
Whether blank lines are ignored. Default is true
csv.Configuration.IgnoreBlankLines = false;
Copy the code
You cannot ignore a line that contains only Spaces or.
AllowComments
Whether comments are allowed, starting with #.
csv.Configuration.AllowComments = true;
Copy the code
Comment
Gets or sets the character used to represent the commented out line. The default is #.
csv.Configuration.Comment = '/';
Copy the code
BadDataFound
Sets up a function that fires when data is incorrect and can be used for logging.
IgnoreQuotes
Gets or sets a value indicating whether quotes should be ignored and treated like any other character when parsing.
The default value is false. If there are quotation marks in the string, there must be three of them “joined together, only one of them will be read in the string”. If there are one of them, the value is ignored.
If true, “is returned as a string.
csv.Configuration.IgnoreQuotes = true;
Copy the code
CsvWriter does not have this property; once the string contains “, it is written as three “joined together.
TrimOptions
Remove space at the beginning and end of fields
csv.Configuration.TrimOptions = TrimOptions.Trim;
Copy the code
PrepareHeaderForMatch
PrepareHeaderForMatch defines the function that matches the property name with the title. Both title and attribute names are run through this function. This feature can be used to remove whitespace from a title or to make a post-case comparison when the title and attribute names are case-insensitive.
csv.Configuration.PrepareHeaderForMatch = (string header, int index) => header.ToLower();
Copy the code