From fb42951dde2d39ccaf64e78348bc352e143d94b5 Mon Sep 17 00:00:00 2001 From: Ted Spence Date: Thu, 9 Oct 2025 12:41:30 -0700 Subject: [PATCH 01/19] Updates from @james-perfectserve --- src/CSVStateMachine.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/CSVStateMachine.cs b/src/CSVStateMachine.cs index 0b97fcc..f92d083 100644 --- a/src/CSVStateMachine.cs +++ b/src/CSVStateMachine.cs @@ -65,6 +65,13 @@ public class CSVStateMachine /// public bool NeedsMoreText() { + // https://github.com/tspence/csharp-csv-reader/issues/68 + // If we're inside a text qualifier, we always need more text + if (_inTextQualifier) + { + return true; + } + return String.IsNullOrEmpty(_line) || _position + _settings.LineSeparator.Length >= _line.Length; } From e67f9da320e1d19cbd55c505408328e03c95ed6f Mon Sep 17 00:00:00 2001 From: Ted Spence Date: Thu, 9 Oct 2025 13:00:08 -0700 Subject: [PATCH 02/19] Replace net50 with net80 Since I last updated this package, Net50 is no longer in support. We can still include NetStandard20 for older packages, but for compiling the main software we need net80. --- .github/workflows/dotnet.yml | 16 +++---- csharp-csv-reader.sln | 11 +---- .../src.net80.csproj} | 2 +- tests/net60/tests.net60.csproj | 43 ------------------- .../tests.net80.csproj} | 6 +-- 5 files changed, 13 insertions(+), 65 deletions(-) rename src/{net50/src.net50.csproj => net80/src.net80.csproj} (93%) delete mode 100644 tests/net60/tests.net60.csproj rename tests/{net50/tests.net50.csproj => net80/tests.net80.csproj} (89%) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 3ccc64e..9f60ba9 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -10,14 +10,14 @@ jobs: build-ubuntu: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v5 name: Checkout Code - name: Setup .NET - uses: actions/setup-dotnet@v1 + uses: actions/setup-dotnet@v5 with: dotnet-version: | - 5.0.x - 6.0.x + 8.0.x + 9.0.x - name: Install NUnit.ConsoleRunner 3.4.0 (compatibility) run: nuget install NUnit.ConsoleRunner -Version 3.4.0 -DirectDownload -OutputDirectory . - name: Install NUnit 3.11.0 (compatibility) @@ -43,10 +43,8 @@ jobs: - name: Test (net45) working-directory: ./tests/net45/bin/Debug/ run: ../../../../NUnit.ConsoleRunner.3.4.0/tools/nunit3-console.exe ./tests.net45.dll - - name: Build (DotNet Core 5.0 and NetStandard 2.0) + - name: Build (DotNet Core 8.0 and NetStandard 2.0) run: dotnet build ./csharp-csv-reader.sln - - name: Test (net50) - run: dotnet test ./tests/net50/tests.net50.csproj - name: SonarCloud Install run: dotnet tool update dotnet-sonarscanner --tool-path /tmp/sonar @@ -56,9 +54,9 @@ jobs: - name: SonarCloud Start run: /tmp/sonar/dotnet-sonarscanner begin /k:"tspence_csharp-csv-reader" /o:"tspence" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.vscoveragexml.reportsPaths=coverage.xml - - name: Test (net60) + - name: Test (net80) run: - /tmp/coverage/dotnet-coverage collect "dotnet test ./tests/net60/tests.net60.csproj" -f xml -o "coverage.xml" + /tmp/coverage/dotnet-coverage collect "dotnet test ./tests/net80/tests.net80.csproj" -f xml -o "coverage.xml" - name: SonarCloud End run: /tmp/sonar/dotnet-sonarscanner end /d:sonar.login="${{ secrets.SONAR_TOKEN }}" diff --git a/csharp-csv-reader.sln b/csharp-csv-reader.sln index 96852a1..5ad1751 100644 --- a/csharp-csv-reader.sln +++ b/csharp-csv-reader.sln @@ -18,11 +18,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{E92F982D .github\workflows\nuget-publish.yml = .github\workflows\nuget-publish.yml EndProjectSection EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "src.net50", "src\net50\src.net50.csproj", "{C78A66F7-113D-452A-989B-306CD6534E7B}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "src.net80", "src\net80\src.net80.csproj", "{C78A66F7-113D-452A-989B-306CD6534E7B}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "tests.net50", "tests\net50\tests.net50.csproj", "{D0F7CD1F-EEA9-4727-94C8-71F69FB456BF}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "tests.net60", "tests\net60\tests.net60.csproj", "{1F5483FB-F3A2-4F92-874C-EE28EDACDF64}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "tests.net80", "tests\net80\tests.net80.csproj", "{D0F7CD1F-EEA9-4727-94C8-71F69FB456BF}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -42,10 +40,6 @@ Global {D0F7CD1F-EEA9-4727-94C8-71F69FB456BF}.Debug|Any CPU.Build.0 = Debug|Any CPU {D0F7CD1F-EEA9-4727-94C8-71F69FB456BF}.Release|Any CPU.ActiveCfg = Release|Any CPU {D0F7CD1F-EEA9-4727-94C8-71F69FB456BF}.Release|Any CPU.Build.0 = Release|Any CPU - {1F5483FB-F3A2-4F92-874C-EE28EDACDF64}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1F5483FB-F3A2-4F92-874C-EE28EDACDF64}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1F5483FB-F3A2-4F92-874C-EE28EDACDF64}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1F5483FB-F3A2-4F92-874C-EE28EDACDF64}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -54,7 +48,6 @@ Global {29D87C9E-D9D0-4EF7-895C-48B36C4CFCC0} = {0CDFDACD-6043-48E8-8AA3-7122461F7C7A} {C78A66F7-113D-452A-989B-306CD6534E7B} = {0CDFDACD-6043-48E8-8AA3-7122461F7C7A} {D0F7CD1F-EEA9-4727-94C8-71F69FB456BF} = {0CDFDACD-6043-48E8-8AA3-7122461F7C7A} - {1F5483FB-F3A2-4F92-874C-EE28EDACDF64} = {0CDFDACD-6043-48E8-8AA3-7122461F7C7A} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {0A368276-2291-4A3B-B4EE-1C2D8042E97D} diff --git a/src/net50/src.net50.csproj b/src/net80/src.net80.csproj similarity index 93% rename from src/net50/src.net50.csproj rename to src/net80/src.net80.csproj index 6fb1ca0..ed1496b 100644 --- a/src/net50/src.net50.csproj +++ b/src/net80/src.net80.csproj @@ -4,7 +4,7 @@ CSVFile CSVFile true - net5.0 + net8.0 HAS_ASYNC;HAS_ASYNC_IENUM; diff --git a/tests/net60/tests.net60.csproj b/tests/net60/tests.net60.csproj deleted file mode 100644 index 0645c8b..0000000 --- a/tests/net60/tests.net60.csproj +++ /dev/null @@ -1,43 +0,0 @@ - - - - CSVFile.Tests.net60 - CSVFile.Tests - false - net6.0 - NETSTANDARD2_0;HAS_ASYNC; - CS1591 - - - - - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - - - - - PackageAssets.csv - PreserveNewest - - - - - diff --git a/tests/net50/tests.net50.csproj b/tests/net80/tests.net80.csproj similarity index 89% rename from tests/net50/tests.net50.csproj rename to tests/net80/tests.net80.csproj index c22f8f5..85856cd 100644 --- a/tests/net50/tests.net50.csproj +++ b/tests/net80/tests.net80.csproj @@ -1,10 +1,10 @@  - CSVFile.Tests.net50 + CSVFile.Tests.net80 CSVFile.Tests false - net5.0 + net8.0 HAS_ASYNC;HAS_ASYNC_IENUM; CS1591 @@ -27,7 +27,7 @@ - + From aedf482ebde55303cc1e324109a41ab97db15735 Mon Sep 17 00:00:00 2001 From: Ted Spence Date: Thu, 9 Oct 2025 13:01:48 -0700 Subject: [PATCH 03/19] Upgrade nuget --- .github/workflows/dotnet.yml | 6 ++++++ .github/workflows/nuget-publish.yml | 12 +++++------- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 9f60ba9..dac09c2 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -18,6 +18,12 @@ jobs: dotnet-version: | 8.0.x 9.0.x + - name: Setup Nuget + uses: nuget/setup-nuget@v2 + with: + nuget-api-key: ${{ secrets.NUGET_API_KEY }} + nuget-version: latest + - name: Install NUnit.ConsoleRunner 3.4.0 (compatibility) run: nuget install NUnit.ConsoleRunner -Version 3.4.0 -DirectDownload -OutputDirectory . - name: Install NUnit 3.11.0 (compatibility) diff --git a/.github/workflows/nuget-publish.yml b/.github/workflows/nuget-publish.yml index 391a618..c62dd7b 100644 --- a/.github/workflows/nuget-publish.yml +++ b/.github/workflows/nuget-publish.yml @@ -13,15 +13,13 @@ jobs: name: Update NuGet package steps: - name: Checkout repository - uses: actions/checkout@v1 + uses: actions/checkout@v5 - name: Setup .NET Core @ Latest - uses: actions/setup-dotnet@v1 + uses: actions/setup-dotnet@v5 with: dotnet-version: | - 5.0.x - 6.0.x - 7.0.x + 8.0.x - name: Build (Framework 2.0) run: msbuild ./src/net20/src.net20.csproj /property:Configuration=Release @@ -35,10 +33,10 @@ jobs: run: dotnet build -c Release ./src/netstandard20/src.netstandard20.csproj - name: Setup Nuget - uses: nuget/setup-nuget@v1 + uses: nuget/setup-nuget@v2 with: nuget-api-key: ${{ secrets.NUGET_API_KEY }} - nuget-version: "5.x" + nuget-version: latest - name: Run Nuget pack run: nuget pack CSVFile.nuspec From 05a7a5e0909c79ee01e525b24ebebd7c9d99a163 Mon Sep 17 00:00:00 2001 From: Ted Spence Date: Thu, 9 Oct 2025 13:03:03 -0700 Subject: [PATCH 04/19] Revert to NuGet 5.x --- .github/workflows/dotnet.yml | 2 +- .github/workflows/nuget-publish.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index dac09c2..ec65568 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -22,7 +22,7 @@ jobs: uses: nuget/setup-nuget@v2 with: nuget-api-key: ${{ secrets.NUGET_API_KEY }} - nuget-version: latest + nuget-version: '5.x' - name: Install NUnit.ConsoleRunner 3.4.0 (compatibility) run: nuget install NUnit.ConsoleRunner -Version 3.4.0 -DirectDownload -OutputDirectory . diff --git a/.github/workflows/nuget-publish.yml b/.github/workflows/nuget-publish.yml index c62dd7b..9cfa254 100644 --- a/.github/workflows/nuget-publish.yml +++ b/.github/workflows/nuget-publish.yml @@ -36,7 +36,7 @@ jobs: uses: nuget/setup-nuget@v2 with: nuget-api-key: ${{ secrets.NUGET_API_KEY }} - nuget-version: latest + nuget-version: '5.x' - name: Run Nuget pack run: nuget pack CSVFile.nuspec From 305c03d7cad98ab06e580e6b6d9451e3da987359 Mon Sep 17 00:00:00 2001 From: Ted Spence Date: Thu, 9 Oct 2025 13:11:38 -0700 Subject: [PATCH 05/19] Switch to Ubuntu 24 --- .github/workflows/dotnet.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index ec65568..a18a524 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -8,7 +8,9 @@ on: jobs: build-ubuntu: - runs-on: ubuntu-latest + # As per https://github.com/NuGet/setup-nuget/issues/168#issuecomment-2576628231 + # Setup Nuget only works on Ubuntu 24 04 + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v5 name: Checkout Code From 54d4dd5ad0f038332b5dd21663144cac21b21944 Mon Sep 17 00:00:00 2001 From: Ted Spence Date: Thu, 9 Oct 2025 13:14:19 -0700 Subject: [PATCH 06/19] Manually installing mono-develop is suggested --- .github/workflows/dotnet.yml | 9 ++++++--- .github/workflows/nuget-publish.yml | 4 ++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index a18a524..344f79b 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -8,9 +8,7 @@ on: jobs: build-ubuntu: - # As per https://github.com/NuGet/setup-nuget/issues/168#issuecomment-2576628231 - # Setup Nuget only works on Ubuntu 24 04 - runs-on: ubuntu-24.04 + runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 name: Checkout Code @@ -20,6 +18,11 @@ jobs: dotnet-version: | 8.0.x 9.0.x + + # As per https://github.com/NuGet/setup-nuget/issues/168#issuecomment-2576628231 + # We are now required to install mono separately + - name: Install Mono + run: sudo apt install mono-devel - name: Setup Nuget uses: nuget/setup-nuget@v2 with: diff --git a/.github/workflows/nuget-publish.yml b/.github/workflows/nuget-publish.yml index 9cfa254..24872ac 100644 --- a/.github/workflows/nuget-publish.yml +++ b/.github/workflows/nuget-publish.yml @@ -32,6 +32,10 @@ jobs: - name: Build (NetStandard 2.0) run: dotnet build -c Release ./src/netstandard20/src.netstandard20.csproj + # As per https://github.com/NuGet/setup-nuget/issues/168#issuecomment-2576628231 + # We are now required to install mono separately + - name: Install Mono + run: sudo apt install mono-devel - name: Setup Nuget uses: nuget/setup-nuget@v2 with: From 00a81aa0492f506acf713139e86eb57605fec08a Mon Sep 17 00:00:00 2001 From: Ted Spence Date: Thu, 9 Oct 2025 13:16:50 -0700 Subject: [PATCH 07/19] Include msbuild --- .github/workflows/dotnet.yml | 2 +- .github/workflows/nuget-publish.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 344f79b..c5d7c9b 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -22,7 +22,7 @@ jobs: # As per https://github.com/NuGet/setup-nuget/issues/168#issuecomment-2576628231 # We are now required to install mono separately - name: Install Mono - run: sudo apt install mono-devel + run: sudo apt install mono-complete msbuild - name: Setup Nuget uses: nuget/setup-nuget@v2 with: diff --git a/.github/workflows/nuget-publish.yml b/.github/workflows/nuget-publish.yml index 24872ac..bcc206a 100644 --- a/.github/workflows/nuget-publish.yml +++ b/.github/workflows/nuget-publish.yml @@ -35,7 +35,7 @@ jobs: # As per https://github.com/NuGet/setup-nuget/issues/168#issuecomment-2576628231 # We are now required to install mono separately - name: Install Mono - run: sudo apt install mono-devel + run: sudo apt install mono-complete msbuild - name: Setup Nuget uses: nuget/setup-nuget@v2 with: From ace04aa0ac41a41524c029ae459ea0250942de5a Mon Sep 17 00:00:00 2001 From: Ted Spence Date: Thu, 9 Oct 2025 13:18:12 -0700 Subject: [PATCH 08/19] Maybe just mono-complete? --- .github/workflows/dotnet.yml | 2 +- .github/workflows/nuget-publish.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index c5d7c9b..fb20306 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -22,7 +22,7 @@ jobs: # As per https://github.com/NuGet/setup-nuget/issues/168#issuecomment-2576628231 # We are now required to install mono separately - name: Install Mono - run: sudo apt install mono-complete msbuild + run: sudo apt install mono-complete - name: Setup Nuget uses: nuget/setup-nuget@v2 with: diff --git a/.github/workflows/nuget-publish.yml b/.github/workflows/nuget-publish.yml index bcc206a..67273e1 100644 --- a/.github/workflows/nuget-publish.yml +++ b/.github/workflows/nuget-publish.yml @@ -35,7 +35,7 @@ jobs: # As per https://github.com/NuGet/setup-nuget/issues/168#issuecomment-2576628231 # We are now required to install mono separately - name: Install Mono - run: sudo apt install mono-complete msbuild + run: sudo apt install mono-complete - name: Setup Nuget uses: nuget/setup-nuget@v2 with: From 3babc68323a4370ad98e0c259998ec02e8b53f35 Mon Sep 17 00:00:00 2001 From: Ted Spence Date: Thu, 9 Oct 2025 13:23:22 -0700 Subject: [PATCH 09/19] Switch to xbuild? --- .github/workflows/dotnet.yml | 12 ++++++------ .github/workflows/nuget-publish.yml | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index fb20306..ed98eba 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -34,23 +34,23 @@ jobs: - name: Install NUnit 3.11.0 (compatibility) run: nuget install NUnit -Version 3.11.0 -DirectDownload -OutputDirectory ./packages - name: Build (Framework 2.0) - run: msbuild ./src/net20/src.net20.csproj + run: xbuild ./src/net20/src.net20.csproj - name: Build (Framework 2.0 Tests) - run: msbuild ./tests/net20/tests.net20.csproj + run: xbuild ./tests/net20/tests.net20.csproj - name: Test (net20) working-directory: ./tests/net20/bin/Debug/ run: ../../../../NUnit.ConsoleRunner.3.4.0/tools/nunit3-console.exe ./tests.net20.dll - name: Build (Framework 4.0) - run: msbuild ./src/net40/src.net40.csproj + run: xbuild ./src/net40/src.net40.csproj - name: Build (Framework 4.0 Tests) - run: msbuild ./tests/net40/tests.net40.csproj + run: xbuild ./tests/net40/tests.net40.csproj - name: Test (net40) working-directory: ./tests/net40/bin/Debug run: ../../../../NUnit.ConsoleRunner.3.4.0/tools/nunit3-console.exe ./tests.net40.dll - name: Build (Framework 4.5) - run: msbuild ./src/net45/src.net45.csproj + run: xbuild ./src/net45/src.net45.csproj - name: Build (Framework 4.5 Tests) - run: msbuild ./tests/net45/tests.net45.csproj + run: xbuild ./tests/net45/tests.net45.csproj - name: Test (net45) working-directory: ./tests/net45/bin/Debug/ run: ../../../../NUnit.ConsoleRunner.3.4.0/tools/nunit3-console.exe ./tests.net45.dll diff --git a/.github/workflows/nuget-publish.yml b/.github/workflows/nuget-publish.yml index 67273e1..c274272 100644 --- a/.github/workflows/nuget-publish.yml +++ b/.github/workflows/nuget-publish.yml @@ -22,11 +22,11 @@ jobs: 8.0.x - name: Build (Framework 2.0) - run: msbuild ./src/net20/src.net20.csproj /property:Configuration=Release + run: xbuild ./src/net20/src.net20.csproj /property:Configuration=Release - name: Build (Framework 4.0) - run: msbuild ./src/net40/src.net40.csproj /property:Configuration=Release + run: xbuild ./src/net40/src.net40.csproj /property:Configuration=Release - name: Build (Framework 4.5) - run: msbuild ./src/net45/src.net45.csproj /property:Configuration=Release + run: xbuild ./src/net45/src.net45.csproj /property:Configuration=Release - name: Build (DotNetCore 5.0) run: dotnet build -c Release ./src/net50/src.net50.csproj - name: Build (NetStandard 2.0) From e476b481926bbe005e4d50e41214b84f372a5dfa Mon Sep 17 00:00:00 2001 From: Ted Spence Date: Thu, 9 Oct 2025 13:28:05 -0700 Subject: [PATCH 10/19] Handle array empty differently for net20 --- src/CSVReader.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/CSVReader.cs b/src/CSVReader.cs index a03727a..547b476 100644 --- a/src/CSVReader.cs +++ b/src/CSVReader.cs @@ -345,7 +345,11 @@ public CSVReader(StreamReader source, CSVSettings settings = null) } } +#if NET20 + Headers = CSV.ParseLine(line, _settings) ?? new Array(); +#else Headers = CSV.ParseLine(line, _settings) ?? Array.Empty(); +#endif } else { @@ -382,7 +386,11 @@ public CSVReader(Stream source, CSVSettings settings = null) } } +#if NET20 + Headers = CSV.ParseLine(line, _settings) ?? new Array(); +#else Headers = CSV.ParseLine(line, _settings) ?? Array.Empty(); +#endif } else { From 9a405bc1bb961a0f52dd66e7bce489e62111a269 Mon Sep 17 00:00:00 2001 From: Ted Spence Date: Thu, 9 Oct 2025 13:31:15 -0700 Subject: [PATCH 11/19] Wrong #if --- src/CSVReader.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CSVReader.cs b/src/CSVReader.cs index 547b476..bcd9677 100644 --- a/src/CSVReader.cs +++ b/src/CSVReader.cs @@ -345,7 +345,7 @@ public CSVReader(StreamReader source, CSVSettings settings = null) } } -#if NET20 +#if NET2_0 Headers = CSV.ParseLine(line, _settings) ?? new Array(); #else Headers = CSV.ParseLine(line, _settings) ?? Array.Empty(); @@ -386,7 +386,7 @@ public CSVReader(Stream source, CSVSettings settings = null) } } -#if NET20 +#if NET2_0 Headers = CSV.ParseLine(line, _settings) ?? new Array(); #else Headers = CSV.ParseLine(line, _settings) ?? Array.Empty(); From 548363132bcae6e9c9be5ca1426e033bedc5ea80 Mon Sep 17 00:00:00 2001 From: Ted Spence Date: Thu, 9 Oct 2025 14:35:30 -0700 Subject: [PATCH 12/19] String array with old style syntax --- src/CSVReader.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CSVReader.cs b/src/CSVReader.cs index bcd9677..bada766 100644 --- a/src/CSVReader.cs +++ b/src/CSVReader.cs @@ -346,7 +346,7 @@ public CSVReader(StreamReader source, CSVSettings settings = null) } #if NET2_0 - Headers = CSV.ParseLine(line, _settings) ?? new Array(); + Headers = CSV.ParseLine(line, _settings) ?? new string[] {}; #else Headers = CSV.ParseLine(line, _settings) ?? Array.Empty(); #endif @@ -387,7 +387,7 @@ public CSVReader(Stream source, CSVSettings settings = null) } #if NET2_0 - Headers = CSV.ParseLine(line, _settings) ?? new Array(); + Headers = CSV.ParseLine(line, _settings) ?? new string[] {}; #else Headers = CSV.ParseLine(line, _settings) ?? Array.Empty(); #endif From 1e4d12e871d34662031516e6d4421b19eb688c53 Mon Sep 17 00:00:00 2001 From: Ted Spence Date: Thu, 9 Oct 2025 14:46:08 -0700 Subject: [PATCH 13/19] Include System.Xml Not sure why this is suddenly needed, but let's try to fix. --- tests/net20/tests.net20.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/net20/tests.net20.csproj b/tests/net20/tests.net20.csproj index d6a6e99..c31e0f0 100644 --- a/tests/net20/tests.net20.csproj +++ b/tests/net20/tests.net20.csproj @@ -44,6 +44,7 @@ + From 71e4b336b19fd94690ad2e9241dad733caeb8893 Mon Sep 17 00:00:00 2001 From: Ted Spence Date: Thu, 9 Oct 2025 14:52:07 -0700 Subject: [PATCH 14/19] Add Xml references for other DotNetFramework tests --- tests/net40/tests.net40.csproj | 1 + tests/net45/tests.net45.csproj | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/net40/tests.net40.csproj b/tests/net40/tests.net40.csproj index e6219c8..8f30b31 100644 --- a/tests/net40/tests.net40.csproj +++ b/tests/net40/tests.net40.csproj @@ -41,6 +41,7 @@ + diff --git a/tests/net45/tests.net45.csproj b/tests/net45/tests.net45.csproj index 1bc8747..b23e492 100644 --- a/tests/net45/tests.net45.csproj +++ b/tests/net45/tests.net45.csproj @@ -41,6 +41,7 @@ + From 458d33636221f0fb6f4970571a7008e63910c485 Mon Sep 17 00:00:00 2001 From: Ted Spence Date: Thu, 9 Oct 2025 14:57:23 -0700 Subject: [PATCH 15/19] One more missing xml reference --- src/net40/src.net40.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/src/net40/src.net40.csproj b/src/net40/src.net40.csproj index e93e89d..0a7e138 100644 --- a/src/net40/src.net40.csproj +++ b/src/net40/src.net40.csproj @@ -34,6 +34,7 @@ + From 8933508876ee60f3492686550846c585a8f22891 Mon Sep 17 00:00:00 2001 From: Ted Spence Date: Thu, 9 Oct 2025 15:05:49 -0700 Subject: [PATCH 16/19] Use old style array syntax for DotNetFramework --- src/CSVReader.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CSVReader.cs b/src/CSVReader.cs index bada766..d2e3ee2 100644 --- a/src/CSVReader.cs +++ b/src/CSVReader.cs @@ -345,7 +345,7 @@ public CSVReader(StreamReader source, CSVSettings settings = null) } } -#if NET2_0 +#if NET2_0 || NET4_0 || NET4_5 Headers = CSV.ParseLine(line, _settings) ?? new string[] {}; #else Headers = CSV.ParseLine(line, _settings) ?? Array.Empty(); @@ -386,7 +386,7 @@ public CSVReader(Stream source, CSVSettings settings = null) } } -#if NET2_0 +#if NET2_0 || NET4_0 || NET4_5 Headers = CSV.ParseLine(line, _settings) ?? new string[] {}; #else Headers = CSV.ParseLine(line, _settings) ?? Array.Empty(); From dedb4ae64502772aea4f1c68f4719daf471340b1 Mon Sep 17 00:00:00 2001 From: Ted Spence Date: Thu, 9 Oct 2025 21:00:54 -0700 Subject: [PATCH 17/19] Add some tests and clean up the nuspec file --- CSVFile.nuspec | 14 +++++----- package.cmd | 4 --- src/CSV.cs | 8 +++--- tests/AsyncReaderTest.cs | 56 ++++++++++++++++++++++++++++++++++++++++ tests/BasicParseTests.cs | 1 + 5 files changed, 69 insertions(+), 14 deletions(-) delete mode 100644 package.cmd diff --git a/CSVFile.nuspec b/CSVFile.nuspec index 38c4850..b130c52 100644 --- a/CSVFile.nuspec +++ b/CSVFile.nuspec @@ -2,7 +2,7 @@ CSVFile - 3.2.0 + 3.2.1 CSVFile Ted Spence Ted Spence @@ -13,13 +13,13 @@ Tiny and fast CSV and TSV parsing library (40KB) with zero dependencies. Compatible with DotNetFramework (2.0 onwards) and DotNetCore. docs/icons8-spreadsheet-96.png - August 5, 2024 + October 9, 2025 - * Fix issue with Windows-style newlines crossing chunks found by @joelverhagen - * Fix issue with endless loops reported by @wvvegt + * Fix issue with loops during text qualifiers, reported by @AlainBartmanDilaw and @james-perfectserve, fix by james + * Update to Net80 for mainstream build, Net50 is no longer relevant docs/README.md - Copyright 2006 - 2024 + Copyright 2006 - 2025 fast csv parser serialization deserialization streaming async @@ -27,7 +27,7 @@ - + @@ -38,6 +38,6 @@ - + diff --git a/package.cmd b/package.cmd deleted file mode 100644 index 810732f..0000000 --- a/package.cmd +++ /dev/null @@ -1,4 +0,0 @@ -@echo off -msbuild csharp-csv-reader.sln /p:configuration=release -..\nuget pack csvfile.nuspec -move *.nupkg ..\nuget-temp-folder diff --git a/src/CSV.cs b/src/CSV.cs index ea77921..15125ca 100644 --- a/src/CSV.cs +++ b/src/CSV.cs @@ -503,12 +503,14 @@ internal static string ItemsToCsv(IEnumerable items, CSVSettings settings, char[ /// The separator public static char? ParseSepLine(string line) { - if (line.StartsWith("sep", StringComparison.OrdinalIgnoreCase)) + // We can't trim whitespace since the separator might be a tab + string spacesRemoved = line.Replace(" ", ""); + if (spacesRemoved.StartsWith("sep", StringComparison.OrdinalIgnoreCase)) { - var equals = line.Substring(3).Trim(); + var equals = spacesRemoved.Substring(3); if (equals.StartsWith("=")) { - var separator = equals.Substring(1).Trim(); + var separator = equals.Substring(1); if (separator.Length > 1) { throw new Exception("Separator in 'sep=' line must be a single character"); diff --git a/tests/AsyncReaderTest.cs b/tests/AsyncReaderTest.cs index 7bcfdc0..c990144 100644 --- a/tests/AsyncReaderTest.cs +++ b/tests/AsyncReaderTest.cs @@ -195,5 +195,61 @@ public async Task TestAlternateDelimiterQualifiers() } } } + + [Test] + public async Task TestChunking() + { + var source = "sep=\t\n" + + "Name\tTitle\tPhone\n" + + "JD\t\"Tallest doctor in the whole wide world\"\tx221\n" + + "Janitor\tJanitor\tx235\n" + + "\"Dr. Reed, " + Environment.NewLine + "Eliot\"\t\"Private \"\"Practice\"\"\"\tx236\n" + + "Dr. Kelso\tChief of Medicine\tx100"; + + // Convert into stream + var settings = new CSVSettings() { + AllowSepLine = true, + HeaderRowIncluded = true, + FieldDelimiter = '\t', + TextQualifier = '\"', + BufferSize = 10, + LineSeparator = "\n" + }; + using (var cr = CSVReader.FromString(source, settings)) + { + Assert.AreEqual("Name", cr.Headers[0]); + Assert.AreEqual("Title", cr.Headers[1]); + Assert.AreEqual("Phone", cr.Headers[2]); + var i = 1; + await foreach (var line in cr) + { + switch (i) + { + case 1: + Assert.AreEqual("JD", line[0]); + Assert.AreEqual("Tallest doctor in the whole wide world", line[1]); + Assert.AreEqual("x221", line[2]); + break; + case 2: + Assert.AreEqual("Janitor", line[0]); + Assert.AreEqual("Janitor", line[1]); + Assert.AreEqual("x235", line[2]); + break; + case 3: + Assert.AreEqual("Dr. Reed, " + Environment.NewLine + "Eliot", line[0]); + Assert.AreEqual("Private \"Practice\"", line[1]); + Assert.AreEqual("x236", line[2]); + break; + case 4: + Assert.AreEqual("Dr. Kelso", line[0]); + Assert.AreEqual("Chief of Medicine", line[1]); + Assert.AreEqual("x100", line[2]); + break; + } + + i++; + } + } + } } } diff --git a/tests/BasicParseTests.cs b/tests/BasicParseTests.cs index 6eea3ab..0185e28 100644 --- a/tests/BasicParseTests.cs +++ b/tests/BasicParseTests.cs @@ -187,6 +187,7 @@ public void ParseSepLineTest() Assert.AreEqual(null, CSV.ParseSepLine("sep=")); Assert.AreEqual(null, CSV.ParseSepLine("sep= ")); Assert.AreEqual(null, CSV.ParseSepLine("sep = ")); + Assert.AreEqual('\t', CSV.ParseSepLine("sep=\t")); Assert.Throws(() => { CSV.ParseSepLine("sep= this is a test since separators can't be more than a single character"); From 66d211953cc85e405aa14006d175426e873beda4 Mon Sep 17 00:00:00 2001 From: Ted Spence Date: Thu, 9 Oct 2025 21:18:04 -0700 Subject: [PATCH 18/19] Sonar items --- src/CSV.cs | 2 +- tests/AsyncReaderTest.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/CSV.cs b/src/CSV.cs index 15125ca..e407a4e 100644 --- a/src/CSV.cs +++ b/src/CSV.cs @@ -508,7 +508,7 @@ internal static string ItemsToCsv(IEnumerable items, CSVSettings settings, char[ if (spacesRemoved.StartsWith("sep", StringComparison.OrdinalIgnoreCase)) { var equals = spacesRemoved.Substring(3); - if (equals.StartsWith("=")) + if (equals.StartsWith('=')) { var separator = equals.Substring(1); if (separator.Length > 1) diff --git a/tests/AsyncReaderTest.cs b/tests/AsyncReaderTest.cs index c990144..9e4b3eb 100644 --- a/tests/AsyncReaderTest.cs +++ b/tests/AsyncReaderTest.cs @@ -66,7 +66,7 @@ public async Task TestBasicReader() Assert.AreEqual("x100", line[2]); break; default: - Assert.IsTrue(false, "Should not get here"); + Assert.Fail("Should not get here"); break; } @@ -139,7 +139,7 @@ public async Task TestDanglingFields() Assert.AreEqual("", line[3]); break; default: - Assert.IsTrue(false, "Should not get here"); + Assert.Fail("Should not get here"); break; } From 7fc5515070a3a56de83ecb3433215e3e93584238 Mon Sep 17 00:00:00 2001 From: Ted Spence Date: Thu, 9 Oct 2025 21:23:30 -0700 Subject: [PATCH 19/19] Update CSV.cs --- src/CSV.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/CSV.cs b/src/CSV.cs index e407a4e..1974613 100644 --- a/src/CSV.cs +++ b/src/CSV.cs @@ -508,7 +508,9 @@ internal static string ItemsToCsv(IEnumerable items, CSVSettings settings, char[ if (spacesRemoved.StartsWith("sep", StringComparison.OrdinalIgnoreCase)) { var equals = spacesRemoved.Substring(3); - if (equals.StartsWith('=')) + + // for compatibility with dotnet framework 2.0, this cannot be a char + if (equals.StartsWith("=")) { var separator = equals.Substring(1); if (separator.Length > 1)