Skip to content

Latest commit

 

History

History
295 lines (232 loc) · 11.6 KB

File metadata and controls

295 lines (232 loc) · 11.6 KB

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[Unreleased]

Fixed

  • CsvWriter not quoting fields that contain a bare carriage return (\r)
    • Per RFC 4180 a field containing CR, LF, the separator, or a quote must be quoted; CsvWriter only triggered on \n, the separator, ', and ", so a value like a\rb was written unquoted — mis-parsed by strict readers and split into two records when re-read
    • CsvBufferWriter already included \r; all CsvWriter paths (sync, async, and the ReadOnlyMemory<char> paths) now match it

Performance

  • Removed a per-row char[] allocation in CsvWriter.WriteLine/WriteLineAsync by caching the fixed quote-trigger characters in a static array and checking the variable separator separately

2.0.245 - 2026-05-17

Fixed

  • Memory-based reader paths dropping records after blank lines (#122)
    • ReadFromMemory and ReadAsSpan from ReadOnlyMemory<char> terminated iteration at the first blank line in the middle of the input
    • All five reader paths now continue parsing past blank lines uniformly
  • Unescaped inner quotes in quoted fields throwing InvalidOperationException (#114)
    • Fields like "JOHN "WAYNE"" (a quoted field containing unescaped inner quotes) now parse leniently with the inner quotes preserved as literal characters
    • Fix landed incidentally with the engine unification in #118; covered by regression tests against the originally reported FMBC_EMPPERS.csv across all read paths
  • Quoted commas split as separate columns when the opening quote was preceded by whitespace under TrimData=true (#71)
    • A, ",," was parsed as four columns because the splitter only entered quote mode when the " sat at the exact field start; the leading space pushed it one position past start and the inner commas were treated as separators
    • With TrimData=true, the splitter now accepts an opening quote after any run of leading whitespace, and IsUnterminatedQuotedValue applies the same leniency so multiline continuation agrees with the splitter
    • Strict (non-TrimData) behavior is preserved: "... without TrimData still parses as an unquoted field

Performance

  • Unified the four CsvReader read loops behind a single JIT-devirtualized engine (#118)
    • Sync, async, span, optimized-memory, and from-memory paths now share one implementation
    • Struct line sources + struct row factories with generic constraints let the JIT monomorphize and inline per call site
    • HeaderAbsent + multiline-first-record fix now applies uniformly to all five paths
  • Dropped the ArrayPool<char> rent/copy/return dance from MemorySliceLineSource.Concat (#119)
    • The pool was rented and immediately discarded on every multiline continuation
    • Direct string.Concat-based path is both simpler and faster
  • Primed the row split cache from the engine's multiline loop (#120)
    • The engine already splits to detect unterminated quoted values; the result is now reused by the row instead of being re-split lazily on first column access
  • Pre-sized the split list using the known header count, avoiding List<T> grow-and-copy on the per-row hot path
  • Cached SearchValues<char> and switched to string.Create in the writer paths
    • CsvBufferWriter.WriteCell and CsvWriter's Memory-variant write paths were allocating a fresh SearchValues<char> on every cell because MemoryExtensions.IndexOfAny(ReadOnlySpan,ReadOnlySpan) builds one internally for vectorized search; now cached in a static field with the variable separator checked via Contains
    • CsvBufferWriter.ToString allocated an intermediate char[] before copying into the final string; now uses string.Create for a single allocation
    • One-shot WriteCsv + ToString allocations dropped from ~3.0x the StringBuilder path to ~0.78x, constant across 100 → 100k rows

Changed

  • Updated dependencies:
    • microsoft.net.test.sdk to 18.5.1 (#117)
    • mstest monorepo to 4.2.3 (#116)

2.0.217 - 2026-01-04

Added

  • AutoRenameHeaders option to handle duplicate and empty headers (#95)
  • WriteAsync support for IEnumerable<string[]> (#104)

Fixed

  • Correct escaped quote detection logic in IsUnterminatedQuotedValue (#110)
    • The modulo check for determining if a quoted field is unterminated was inverted
    • Fields ending with escaped quotes (e.g., "test""" for value test") were incorrectly detected as unterminated
    • This caused rows to merge together when AllowNewLineInEnclosedFieldValues was enabled
  • Resolve build warnings and test failures

Performance

  • Pre-allocate list capacity in SplitLine (#113)

Changed

  • Updated dependencies:
    • actions/checkout to v6 (#108)
    • microsoft.net.test.sdk to 18.0.1
    • mstest monorepo to 4.0.2

2.0.205 - 2025-10-21

Added

  • Support for nullable headers and convenience overloads (#66)
  • Span/Memory APIs for .NET 8.0+ for high-performance scenarios
  • .NET 9 support in tests (#92)
  • .NET 9 setup for CodeQL workflow (#91)

Fixed

  • Correct header count for HeaderAbsent mode with multiline fields (#72)
  • Compile error in Assert.Throws
  • Relaxed performance test thresholds for CI environments

Changed

  • Moved PRD to docs folder and updated documentation guidelines
  • Enhanced documentation with architecture details and NuGet badges
  • Updated dependencies:
    • mstest monorepo to v4
    • microsoft.net.test.sdk to v18
    • github/codeql-action to v4
    • actions/stale to v10
    • actions/setup-dotnet to v5
    • actions/checkout to v5
    • microsoft.net.test.sdk to 17.14.1
    • mstest monorepo to 3.9.3

Performance

  • Eliminated regex usage in CSV parsing for better performance

2.0.170 - 2025-05-20

Added

  • AllowEnclosedFieldValues option (#51, #84)
  • LineHasColumn method to check if a column exists (#32, #90)
  • WriteAsync overload with CancellationToken support (#76)
  • Comprehensive test coverage for:
    • Comma inside quoted text (#73, #86)
    • Invalid CSV scenarios (#87)
    • Async operations (#88)
    • Skip-header functionality (#88)

Fixed

  • Writer null cell handling (#74, #83)
  • Environment.NewLine usage in writer tests (#89)

Changed

  • Removed regex splitting in favor of more efficient parsing (#82)
  • Expanded README with async and helper APIs documentation (#85)
  • Updated target frameworks and NuGet properties
  • Updated tests to .NET 9
  • Updated dependencies:
    • mstest monorepo to 3.9.0
    • microsoft.net.test.sdk to 17.14.0
    • github/codeql-action to v3
    • mstest monorepo to 3.8.3

2.0.128 - 2025-02-20

Added

  • .NET 8.0 target framework support
  • Trimming and AOT (Ahead-of-Time compilation) support
  • Collection expressions support
  • Additional .NET 8 method overloads

Changed

  • Deprecated .NET Standard 1.0 target (no longer recommended)
  • Fixed NuSpec paths
  • Code cleanup: warnings and whitespace
  • ReSharper code style improvements
  • Updated dependencies:
    • actions/checkout to v4
    • actions/stale to v9
    • microsoft.net.test.sdk to v17.6.0 (#61)
    • microsoft.net.test.sdk to v17.5.0 (#58)
    • actions/stale to v7 (#59)

2.0.93 - 2022-12-10

Changed

  • Updated microsoft.net.test.sdk to v17.4.0 (#55)
  • Updated microsoft.net.test.sdk to v17.3.2 (#53)
  • Updated actions/stale to v6 (#54)

2.0.87 - 2022-09-02

Added

  • Async methods for Write and WriteToText (#52)
  • Support for IAsyncEnumerable<string[]>

Fixed

  • Various fixes for async write operations (#52)

Changed

  • Updated mstest monorepo to v2.2.10 (#40)

2.0.84 - 2022-05-04

Added

  • GetColumn and GetBlock extension methods (#46)
    • GetColumn(int columnNo) and GetColumn(int columnNo, Func<string, T>)
    • GetBlock(int row_start, int row_length, int col_start, int col_length)

Changed

  • Updated github/codeql-action to v2 (#45)

2.0.80 - 2022-04-21

Changed

  • Updated microsoft.net.test.sdk to v17 (#43)
  • Updated multiple dependencies:
    • microsoft.net.test.sdk to v15.9.2 (#37)
    • microsoft.sourcelink.github to v1.1.1 (#38)
    • actions/checkout to v3 (#41)
    • actions/stale to v5 (#42)

2.0.76 - 2022-04-21

Changed

  • Updated mstest monorepo to v2 (#44)

2.0.67 - 2022-03-31

Added

  • Renovate configuration for automated dependency updates (#36)

2.0.65 - 2022-01-18

Fixed

  • Fixed issue #35 with proper test coverage

2.0.64 - 2021-12-26

Added

  • Option to skip header when writing CSV files

2.0.62 - 2020-12-24

Changed

  • Moved custom logic from SplitLine to CsvLineSplitter

Performance

  • Improved performance for .Replace call

2.0.61 - 2020-12-23

Added

  • Span/Memory support for .NET Core 3.1 and .NET Standard 2.1
  • .NET Core 3.1 support
  • .NET Standard 2.1 target (enables use in Blazor WASM projects) (#29)
  • CodeQL analysis workflow

Fixed

  • Fixed issue #28

Performance

  • Prefer Span/Memory APIs for better performance on supported frameworks

Earlier Versions

[1.x] - 2015-2020

The library was initially released with comprehensive CSV reading and writing functionality:

Core Features

  • CSV reading from TextReader, Stream, and string
  • CSV writing with header support
  • Configurable separators with auto-detection
  • Header row handling (present/absent modes)
  • Quote and escape character handling
  • Multiline field support (#24)
  • Column access by name or index
  • Custom row validation and skipping

Configuration Options (CsvOptions)

  • RowsToSkip and SkipRow for filtering
  • TrimData for whitespace handling
  • Comparer for case-insensitive column names
  • ValidateColumnCount for strict validation
  • ReturnEmptyForMissingColumn for flexible access
  • Aliases for alternative column names
  • AllowNewLineInEnclosedFieldValues for multiline fields
  • AllowBackSlashToEscapeQuote for escape sequences
  • AllowSingleQuoteToEncloseFieldValues for single-quote support

Additional Functionality

  • SourceLink support (2018-08-28)
  • CsvWriter class for generating CSV output (2018-02-14)
  • Values property to retrieve all row values (#16)
  • codecov integration (2019-02-17)
  • CodeQL analysis (2020-10-02)

Bug Fixes

  • Fixed issues #10, #11, #14, #19, #28, #35
  • Fixed multiline parsing bugs (#24)
  • Fixed unterminated quoted value detection

Framework Support

  • Initial targets: .NET Standard 1.3, .NET 4.0
  • Added .NET Standard 2.0 support
  • Added .NET Standard 2.1 support (2020)
  • Added .NET Core 3.1 support (2020)

For more details on each release, see the commit history or visit the NuGet package page.