Page cover image

CSV

Read

Perigee ships with several powerful CSV tools that make reading even complicated CSV's very easy and fast with memory efficient span based data reads.

//Get a memory stream to the file
using MemoryStream ms = new MemoryStream(File.ReadAllBytes("Products.csv"));

//Read the CSV as a list of T classes
List<Product> products = CSVReader.ReadAs<Product>(ms);

//Read the csv as a DataTable
DataTable ProductTable =  CSVReader.ToDataTable(ms, out var res);

When using the .ToDataTable() methods, you get the resulting parse parameters sent back as an out variable. This allows you to check it's encoding, formatting, delimiters, header row location, etc.

Write

To write CSV data supply a DataTable and any additional handlers to override specifics on a data type.

  • We'll read in the Products.CSV as our source.

  • Let's then declare a writer, and set it to BAR delimited

  • Register a decimal handler that write's any decimals with 3 digits after the period

    • The handler sends you back the object (in this case a decimal)

    • The Row Index.

    • The Column Name.

    • It expects a return value of the string converted version, as well as a boolean indicating if the transform was successful.

    • Any NON-SUCCESSFUL transformed handlers are added to the writers LoadLog property and can be viewed after conversion.

  • Then simply call .Write().

//Read products CSV from above reader demo
using MemoryStream ms = new MemoryStream(File.ReadAllBytes("Products.csv"));
DataTable ProductTable = CSVReader.ToDataTable(ms, out var res);

//Write this table back out to CSV using a custom decimal format and BAR delimited
CSVWriter writer = new CSVWriter(ProductTable, (d) => "Products").WithDelimiter("|");

//You can register booleans, strings, datetimes, decimals... etc.
writer.RegisterHandler<decimal>((dec, rowIndex, colName) => new Tuple<string, bool>(dec.ToString("N3"), true));    

//Write it out
string content = writer.Write();
writerResult.csv
Products
ID|PRODUCT|PRICE
1|MILK|8.990
2|55-INCH TV|899.990
3|BREAD|1.990

Clean

Maybe the only thing you need to do is take the absolutely horrendous CSV data in the Sample Data section and just create a CSV that can be cleanly loaded into another system.

using MemoryStream ms = new MemoryStream(File.ReadAllBytes("Products.csv"));

string cleanContent = CSVReader.Clean(ms);

This transforms the very badly formatted CSV Sample Data into this:

ID,PRODUCT,PRICE
1,MILK,8.99
2,55-INCH TV @ aisle 4,899.99
3,BREAD,1.99

Sample Data

Included is the sample data and classes used above.

Products.csv
CSVData as of 1/1/2001
By: Yours Truly
ID@PRODUCT@PRICE
1@[email protected]
2@'55-INCH TV @ aisle 4'@899.99
3@[email protected]
public class Product
{
    public int id { get; set; } = 0;
    public string product { get; set; }
    public decimal price { get; set; }
}

Last updated