Really simple csv library
This library targets .NET Standard 2.0, .NET 8.0, and .NET 9.0, with enhanced Span/Memory APIs available for .NET 8.0+.
To install csv, use the following command in the Package Manager Console
PM> Install-Package Csv
For a detailed list of changes and version history, see CHANGELOG.md.
More examples can be found in the tests.
// NOTE: Library assumes that the csv data will have a header row by default, see CsvOptions.HeaderMode/*# comments are ignoredColumn name,Second column,Third columnFirst cell,second cell,Second row,second cell,third cell*/varcsv=File.ReadAllText("sample.csv");foreach(varlineinCsvReader.ReadFromText(csv)){// Header is handled, each line will contain the actual row datavarfirstCell=line[0];varbyName=line["Column name"];}CsvReader also supports reading from a TextReader (CsvReader.Read(TextReader, CsvOptions)) or a Stream (CsvReader.ReadFromStream(Stream, CsvOptions))
For .NET 8.0+ the library exposes:
CsvReader.ReadAsyncandCsvReader.ReadFromStreamAsyncwhich returnIAsyncEnumerable<ICsvLine>CsvReader.ReadFromMemoryto read from aReadOnlyMemory<char>without allocating intermediate stringsCsvReader.ReadAsSpan,CsvReader.ReadFromStreamAsSpan, andCsvReader.ReadFromTextAsSpanwhich returnIEnumerable<ICsvLineSpan>for zero-allocation Span/Memory access to CSV dataCsvReader.ReadFromMemoryOptimizedwithCsvMemoryOptionsfor high-performance scenarios using ArrayPool-based buffering
varcsv=File.ReadAllText("sample.csv");foreach(varlineinCsvReader.ReadFromTextAsSpan(csv)){// Access data as ReadOnlySpan<char> for zero allocationsReadOnlySpan<char>firstCell=line.GetSpan(0);ReadOnlySpan<char>byName=line.GetSpan("Column name");// Or as ReadOnlyMemory<char> if you need to store referencesReadOnlyMemory<char>cellMemory=line.GetMemory(0);}CsvOptions can be used to configure the csv parsing:
varoptions=newCsvOptions// Defaults{RowsToSkip=0,// Allows skipping of initial rows without csv dataSkipRow=(row,idx)=>string.IsNullOrEmpty(row)||row[0]=='#',Separator='\0',// Autodetects based on first rowTrimData=false,// Can be used to trim each cellComparer=null,// Can be used for case-insensitive comparison for namesHeaderMode=HeaderMode.HeaderPresent,// Assumes first row is a header rowAutoRenameHeaders=true,// Automatically renames duplicate headers (e.g., "A", "A2", "A3") and converts empty headers to "Empty", "Empty2", etc. Set to false to throw on duplicates.ValidateColumnCount=false,// Checks each row immediately for column countReturnEmptyForMissingColumn=false,// Allows for accessing invalid column namesAliases=null,// A collection of alternative column namesAllowNewLineInEnclosedFieldValues=false,// Respects new line (either \r\n or \n) characters inside field values enclosed in double quotes.AllowBackSlashToEscapeQuote=false,// Allows the sequence "\"" to be a valid quoted value (in addition to the standard """")AllowSingleQuoteToEncloseFieldValues=false,// Allows the single-quote character to be used to enclose field valuesNewLine=Environment.NewLine// The new line string to use when multiline field values are read (Requires "AllowNewLineInEnclosedFieldValues" to be set to "true" for this to have any effect.)};varcolumnNames=new[]{"Id","Name"};varrows=new[]{new[]{"0","John Doe"},new[]{"1","Jane Doe"}};varcsv=CsvWriter.WriteToText(columnNames,rows,',');File.WriteAllText("people.csv",csv);/*Writes the following to the file:Id,Name0,John Doe1,Jane Doe*/varrows=new[]{new[]{"0","John Doe"},new[]{"1","Jane Doe"}};// Convenience overload - no need to pass headers or skipHeaderRowvarcsv=CsvWriter.WriteToText(rows);File.WriteAllText("people.csv",csv);/*Writes the following to the file (no header row):0,John Doe1,Jane Doe*/varcolumnNames=new[]{"Id","Name"};varrows=new[]{new[]{"0","John Doe"},new[]{"1","Jane Doe"}};// Pass null for headers and skipHeaderRow: true// Column count is determined from the first data rowvarcsv=CsvWriter.WriteToText(null,rows,',',skipHeaderRow:true);varrows=new[]{new[]{"A","B"},new[]{"C","D"}};varcsv=CsvWriter.WriteToText(rows,';');// semicolon separator// Output: A;B// C;DCsvWriter also includes asynchronous overloads (WriteAsync and
WriteToTextAsync) which operate on IAsyncEnumerable<string[]> and support
passing a CancellationToken. For .NET 8.0+, memory-efficient overloads using
ReadOnlyMemory<char> are available.
CsvReader provides extension methods to work with the returned
IEnumerable<ICsvLine>:
GetColumn(int columnNo)/GetColumn<T>(int columnNo, Func<string, T>)– extract a single column from all rows.GetBlock(int row_start = 0, int row_length = -1, int col_start = 0, int col_length = -1)– get a rectangular subset of the data.