NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
NuGet · #92 most downloaded on NuGet
A library for reading and writing CSV files. Extremely fast, flexible, and easy to use. Supports reading and writing of custom class objects.
Last release 1 years ago
02 Jun 2025
Ships unpredictably
gaps range from 8 days to 1.2 years
Nearly every release is documented
notes for 60 of the last 60 stable releases
10 versions withdrawn
withdrawn after publishing
127 years old
236 releases · first in 1900
Updated docs change log and build.
Updated docs change log and build.
Use Attributes.IsDefined instead of Attributes.GetCustomAttributes to check for attributes on a type. This is more performant.
Removed out of support frameworks net6.0 and net7.0 and added net9.0 .
Use CacheKey struct for ObjectCreator cache key.
Early exit in ObjectCreator when there are no args. This reduces allocations.
Add Dispose and DisposeAsync to writer write async methods.
Fixed issue with setting UseDefaultOnConversionFailure to true when the default value is null .
Added more nullability.
Added more nullability.
One column per quarter.
Moved Microsoft.Bcl.AsyncInterfaces to 8.0.0.
Nullable turned on.
Moved Microsoft.Bcl.AsyncInterfaces to 8.0.0.
Dispose of IEnumerator in CsvWriter.
Dispose of IEnumerator in CsvWriter.
Fixed issue with writing where an IEnumerable was getting projected t…
Fixed issue with writing where an IEnumerable was getting projected t…
Fully implemented IDictionary on FastDynamicObject .
Reading and writing performance optimizations when using multiple records.
Reading and writing performance optimizations when using multiple records.
Reading and writing performance optimizations when using dynamic .
Changed RecordWriter.CreateWriteDelegate<T>(T record) to RecordWriter.CreateWriteDelegate<T>(Type type) .
Changed DynamicRecordWriter.CreateWriteDelegate<T>(T record) to DynamicRecordWriter.CreateWriteDelegate<T>(Type type) .
Changed ExpandoObjectRecordWriter.CreateWriteDelegate<T>(T record) to ExpandoObjectRecordWriter.CreateWriteDelegate<T>(Type type) .
Changed ObjectRecordWriter.CreateWriteDelegate<T>(T record) to ObjectRecordWriter.CreateWriteDelegate<T>(Type type) .
Changed PrimitiveRecordWriter.CreateWriteDelegate<T>(T record) to PrimitiveRecordWriter.CreateWriteDelegate<T>(Type type) .
Changed RecordWriterFactory.MakeRecordWriter<T>(T record) to RecordWriterFactory.MakeRecordWriter<T>(RecordTypeInfo typeInfo) .
Removed RecordManager.Create methods. Use Func<T> RecordManager.GetReadDelegate<T>(Type recordType) instead.
Removed RecordManager.Write methods. Use Action<T> RecordManager.GetWriteDelegate<T>(RecordTypeInfo typeInfo) instead.
Removed RecordCreator.Create methods. Use Func<T> RecordCreator.GetCreateRecordDelegate<T>(Type recordType) instead.
Removed RecordWriter.Create methods. Use Action<T> RecordWriter.GetWriteDelegate<T>(RecordTypeInfo typeInfo) instead.
Changed RecordWriterFactory.MakeRecordWriter<T>(T record) to RecordWriterFactory.MakeRecordWriter(RecordTypeInfo typeInfo) .
Changed GuidConverter to throw TypeConverterException instead of FormatException to be consistent with other converters.
Fixed issue with TypeConverter where T is Nullable did not work.
Removed dependency on System.Linq.Async .
Added InformationalVersion to assembly info.
Created generic TypeConverter class to allow for easier creation of type converters.
TypeConverter was renamed to NotSupportedTypeConverter .
TypeConverter is now a generic type converter base class.
Added static CsvConfiguration.WithAttributes method to create a new configuration with attributes applied.
Added static CsvConfiguration.WithAttributes method to create a new configuration with attributes applied.
Boolean attributes have empty overload that default to true.
ShouldQuote optimizations.
Fixed issue with quotes at end of line getting ignore when LineBreakInQuotedFieldIsBadData is enabled.
Fixed issue where calling Convert on empty Map() would throw an exception.
Fixed issue where writing with HasHeaderRecord set to false was writing a header record.
Fixed issue where exception This Operation is only valid on generic types was being thrown.
Fixed issue where CsvDataReader couldn't be used if lines were read manually ahead of time.
Fixed issue where CsvDataReader wasn't working when HasHeaderRecord was false.
Fixed issue where CsvReader.ColumnCount did not match CsvParser.Count .
Fixed issue where GetDelimiter was not detecting the correct delimiter when there are blank lines.
Fixed issue where header validation was outputing error message for each field when it only needed to once.
Fixed issue with .NET 7/8 not having support for DateOnly and TimeOnly.
Fixed issue when writing with the escape char not being escaped if it was different than the quote char.
Fixed issue when writing with the escape char not being escaped if it was different than the quote char.
Fixed issue with CsvWriter not passing leavOpen parameter to other constructor call.
Fixed issue with TypeConverter being assigned to a member that has a Convert expression assigned to it.
Added Field and RawRecord to BadDataException .
Added Field and RawRecord to BadDataException .
Pass IWriterConfiguration into CsvWriter constructor instead of CsvConfiguration .
Allow inherited header prefixes.
Allow mapping to dynamic properties.
Added MemberName to the type converter exception message.
Added MaxFieldSize configuration. If max size is set and the size is reached, MaxFieldSizeException is thrown.
Added class level attribute capability.
New Attributes:
BufferSizeAttribute
CacheFieldsAttribute
CommentAttribute
CountBytesAttribute
DelimiterAttribute
DetectColumnCountChangesAttribute
DetectDelimiterAttribute
DetectDelimiterValueAttribute
EncodingAttribute
EscapeAttribute
ExceptionMessagesContainRawDataAttribute
HasHeaderRecordAttribute
IgnoreBlankLinesAttribute
IgnoreReferencesAttribute
IncludePrivateMembersAttribute
InjectionCharactersAttribute
InjectionEscapeCharacterAttribute
InjectionOptionsAttribute
LineBreakInQuotedFieldIsBadDataAttribute
MaxFieldSizeAttribute
ModeAttribute
NewLineAttribute
ProcessFieldAttribute
QuoteAttribute
TrimOptionsAttribute
UseNewObjectForNullReferenceMembersAttribute
WhiteSpaceCharsAttribute
Added params object[] constructorArgs to TypeConverterAttribute .
Added validation message expression to Validate mapping.
Added IReaderRow to ValidateArgs .
Relax Default and Constant type constraints to IsAssignableFrom .
Added null check in WriteRecords .
Fixed interpolation in exception message.
Fixed constructor mapping issue where parameter has a type converter but would still try and use constructor mapping.
Added string field and string rawRecord to BadDataException constructor.
Added double MaxFieldSize { get; } to IParserConfiguration .
Added bool LeaveOpen { get; } to IWriterConfiguration .
Added bool LeaveOpen { get; } to IParserConfiguration .
Added IReaderRow row to ValidateArgs constructor.
Added support for TypeConverter factories. This allows for the ability to handle many types at once. Code that manually handle nullable, enums, and co
Added support for TypeConverter factories. This allows for the ability to handle many types at once. Code that manually handle nullable, enums, and collections were changed into factories.
Moved delimiter detection into a configuration function. This allows for a user to easily change the detection logic. Default logic is in ConfigurationFunction.GetDelimiter .
Changed CsvConfiguration.SanitizeInjection flag to CsvConfiguration.InjectionOptions enum.
Options are:
None - Default. Does no injection protection. The is default because it's not a part of CSV and is used for an external tool.
Escape - Escapes the field based on OWASP recommendations if an injection char is detected.
Strip - Removes the injection character.
Exception - Throws an exception if an injection char is detected.
Added \t and \r to CsvConfiguration.InjectionEscapeCharacter .
Changed CsvConfiguration.InjectionEscapeCharacter from \t to ' .
CsvDataReader.GetDataTypeName will use types when the schema table is overridden.
More detail added to CsvConfiguration.Validate exception messages.
Reduce double dictionary lookup in a few places.
Fixed issues with delimiter detection logic.
Missing ConfigureAwait(false) added to async calls.
Fixed issue with CsvReader.TryGetField throwing an exception when multiple headers are read.
Fixed issue with MemberMap.Validate passing the wrong type into the expression call.
Fixed issue with MemberMap<T>.Convert not working with static methods.
Fixed issue with DateTimeConverter and DateTimeOffsetConverter throwing an exception other than TypeConverterException on failure.
Fixed issue where MissingFieldFound was not being called if IgnoreBlankLines was off.
CsvConfiguration.SanitizeForInjection -> CsvConfiguration.InjectionOptions
bool IWriterConfiguration.SanitizeForInjection -> InjectionOptions IWriterConfiguration.InjectionOptions
CsvConfiguration.InjectionEscapeCharacter changed from \t to ' .
Added \t and \r to CsvConfiguration.InjectionCharacters .
Added GetDelimiter IParserConfiguration.GetDelimiter delegate.
Disabled nullable until all null issues are fixed.
Updated delimiter detection algorithm.
Updated delimiter detection algorithm.
Strips escaped text based on mode.
Only looks for delimiters that appear on every line.
Uses CultureInfo.TextInfo.ListSeparator if it's on every line.
Cache processed fields in parser so they're not processed on every access.
Cache CsvParser.Record[] so multiple calls wont' regenerate it.
ShouldSkipRecord is null by default and won't get called if not set.
ShouldSkipRecordArgs holds IReaderRow now instead of string[] .
Changed CsvParser constructor to take in IParserConfiguration instead of CsvConfiguration .
Changed CsvReader constructor to take in IReaderConfiguration instead of CsvConfiguration .
Fixed issue where collection types weren't getting the correct MemberMapData passed to them when converting the item.
Fixed issue where BadDataFound was being called multiple times for the same field.
Fixed issue where you can't read with no header when a name has been mapped.
Fixed issue where quoted fields not correctly being identified if there was a buffer swap on white space before quote.
ShouldSkipRecordArgs holds IReaderRow now instead of string[] .
Removed ConfigurationFunctions.ShouldSkipRecord as the default is now null .
Added IParserConfiguration.Validate .
Changed dependencies to minimal needed version.
Support for net60 DateOnly and TimeOnly types.
Fixed issue with delimiter detection in parser async read.
Added IgnoreBaseAttribute to not look at the base class when auto mapping.
Changed delimiter detection to look line by line instead of the full buffer.
Specified exact dependency version matches.
Fixed issue with delimiter detection.
\t wasn't removed and just an exception was being thrown.
Config option to auto detect delimiter. Off by default.
Config option to auto detect delimiter. Off by default.
Added ability to apply a type converter to all registered types.
Added ability to apply type converter options to all registered types.
Added ability to pass an IAsyncEnumerable to WriteRecords.
Added option to use default value on conversion failure.
Added IParserConfiguration.DetectDelimiter .
Added IParserConfiguration.DetectDelimiterValues .
Added IWriter.WriteRecordsAsync<T>(IAsyncEnumerable<T> records, CancellationToken cancellationToken = default) .
Removed \t from CsvConfiguration.WhiteSpaceChars as a default.
Allow schema of destination table to be specified in CsvDataReader.
Fixed issue with constant not working when the field is missing.
Added configuration for ExceptionMessagesContainRawData that defaults to true.
Removed all init properties. These were causing people too many problems.
Fixed issue with exception message not containing the header record.
Added bool IParserConfiguration.ExceptionMessagesContainRawData { get; } .
Added bool IWriterConfiguration.ExceptionMessagesContainRawData { get; } .
All delegate args objects have init removed and now have constructors with parameters.
BadDataFound
ConvertFromString
GetConstructor
GetDynamicPropertyName
HeaderValidated
MissingFieldFound
PrepareHeaderForMatch
ReadingExceptionOccurred
ReferenceHeaderPrefix
ShouldQuote
ShouldSkipRecord
ShouldUseConstructorParameter
Validate
Fixed stack overflow issue with accessing Parser[int] or Parser.Record in BaddataFound callback. Throws an exception explaining issue now.
Fixed issue with Trimming all white space.
Added CancellationToken to reading and writing async methods.
Fixed issue with ShouldQuote not having the correct field type when writing records instead of fields.
Fixed issue with CharCount and ByteCount when trimming.
void IWriterRow.WriteConvertedField(string field) -> void IWriterRow.WriteConvertedField(string field, Type fieldType)
void CsvWriter.WriteConvertedField(string field) -> void CsvWriter.WriteConvertedField(string field, Type fieldType)
…parameters to be added later without a breaking change.
Changed public init properties to set . Once VB.NET implements init , it can change back.
Made method CsvWriter.WriteBuffer protected so sub classes can write fields.
CsvWriter.Flush and CsvWriter.FlushAsync will now flush the underlying TextWriter .
Changed all delegate methods to accept an args struct instead of parameters. This makes it easier to understand what parameters are passed in, and allows for additional parameters to be added later without a breaking change.
Removed the large CsvConfiguration constructor. The properties are now settable, so this isn't needed for VB.NET.
All delegates now take in a single struct argument.
BadDataFound
ConvertFromString
GetConstructor
GetDynamicPropertyName
HeaderValidated
MissingFieldFound
PrepareHeaderForMatch
ReadingExceptionOccurred
ReferenceHeaderPrefix
ShouldQuote
ShouldSkipRecord
ShouldUseConstructorParameter
Validate
Fixed issue with data corruption when parser buffer ran out in middle of escape and quote.
Fixed issue where CsvConfiguration.NewLine was being set when value is null in constructor causing IsNewLine to be true.
#### Features - Added [EnumIgnoreAttribute] .
Changed ParserMode to CsvMode and added the modes to CsvWriter .
Changed ParserMode to CsvMode and added the modes to CsvWriter .
Added Type fieldType parameter to ShouldQuote delegate.
Added TypeConverterOptions.EnumIgnoreCase (default is false). Allows EnumConverter to ignore case when matching enum names, values, or NameAttribute .
ParserMode -> CsvMode
Added IParserConfiguration.ProcessFieldBufferSize .
Added IWriterConfiguration.Mode .
ShouldQuote(string, IWriterRow) -> ShouldQuote(string, Type, IWriterRow) .
EnumConverter was changed to case sensitive by default.
Fixed issue with CsvContext not being passed into AutoMap.
Added back Excel compatibility for bad data fallback.
Added back Excel compatibility for bad data fallback.
If a field doesn't start with a Quote , read until a Delimiter or NewLine is found.
If in quoted field and a Quote is found that isn't preceded by an Escape , read until a Delimiter or NewLine` is found.
TrimOptions.Trim will be applied before these rules.
Fixed issue with processed field buffer not being large enough on resize.
Process boolean and null type converter options when writing.
Fixed parsing issue with state not being reset when buffer is filled in the middle of a state.
Fixed parsing issue with buffer ending in the middle of a line ending.
Added ParserMode.NoEscape. This will ignore quotes and escape characters.
Fixed issue with writing a field that is larger then 2x the buffer size.
Fixed issue with VB not being able to set init properties on CsvConfiguration by adding a constructor that takes in all properties as optional named a
Nothing published for this version
Fixed issue with cache miss in on both the reader and writer.
No changes.
No changes.
Fixed issue with CsvConfiguration.NewLine not defaulting to '\r\n'.
Fixed issue with CsvWriter not keeping track of Row and Index .
CsvConfiguration.NewLine changed to a string . You can now read and write any string you like for a line ending. This defaults to Environment.NewLine
Fixed issue with other platforms than net50 using init .
Fixed issue with being unable to write \r\n in an environment that does use that for Environment.NewLine .
Changed CsvConfiguration to a read only record to eliminate threading issues.
Parser performance.
Writer performance.
Changed CsvConfiguration to a read only record to eliminate threading issues.
Unix parsing mode. Uses escape character instead of field quoting. Configurable NewLine .
Field caching. Disabled by default. When enabled, this will cache all fields created so duplicate fields won't need to create a new string from a character array.
Removed Caches enum.
ReadingContext and WritingContext were merged into a single CsvContext . Anywhere that used either was changed to CsvContext .
All Func s and Action s now have their own delegate .
ConvertUsing renamed to Convert .
ShouldQuote now takes in IWriterRow instead of CsvContext .
CsvConfiguration changed from a class to a record .
All CsvConfiguration properties changed to read only get; init; .
CsvConfiguration.NewLine changed to char? .
CsvConfiguration.NewLineString removed.
CsvConfiguration.RegisterClassMap moved to CsvContext .
CsvConfiguration.UnregisterClassMap moved to CsvContext .
CsvConfiguration.AutoMap moved to CsvContext .
All IParserConfiguration setters removed.
bool IParserConfiguration.CacheFields added.
bool IParserConfiguration.LeaveOpen added.
char? IParserConfiguration.NewLine added.
ParserMode IParserConfiguration.Mode added.
IParserConfiguration.IgnoreQuotes removed.
char[] IParserConfiguration.WhiteSpaceChars added.
All IReaderConfiguration setters removed.
IReaderConfiguration.TypeConverterOptionsCache removed.
IReaderConfiguration.TypeConverterCache removed.
IReaderConfiguration.Maps removed.
IReaderConfiguration.RegisterClassMap removed.
IReaderConfiguration.UnregisterClassMap removed.
IReaderConfiguration.AutoMap removed.
ISerializerConfiguration removed and properties added to IWriterConfiguration .
All IWriterConfiguration setters removed.
IWriterConfiguration.QuoteString removed.
IWriterConfiguration.TypeConverterCache removed.
IWriterConfiguration.MemberTypes removed.
IWriterConfiguration.Maps removed.
IWriterConfiguration.RegisterClassMap removed.
IWriterConfiguration.UnregisterClassMap removed.
IWriterConfiguration.AutoMap removed.
MemberMap.Optional added.
MemberMap<TClass, TMember>.ConvertUsing renamed to Convert .
CsvFieldReader removed.
CsvParser.Read returns boolean instead of string[] .
CsvParser constructors that take in a FieldReader removed.
CsvParser[int index] added to retrieve fields after a Read .
CsvSerializer removed.
IFieldReader removed.
IParser.ByteCount added.
IParser.CharCount added.
IParser.Count added.
IParser[int index] added.
IParser.Record added.
IParser.RawRecord added.
IParser.Row added.
IParser.RawRow added.
IParser.Read returns bool instead of string[] .
IParser.ReadAsync returns bool instead of string[] .
IReader.Parser removed.
int IReaderRow.ColumnCount added.
int IReaderRow.CurrentIndex added.
string[] IReaderRow.HeaderRecord added.
IParser IReaderRow.Parser added.
ISerializer removed.
string[] IWriterRow.HeaderRecord added.
int IWriterRow.Row added.
int IWriterRow.Index added.
RecordBuilder removed.
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →