From 7c19212e55584a42e70df9f3a415f0fca22008f2 Mon Sep 17 00:00:00 2001 From: Tatsuro Shibamura Date: Fri, 4 Mar 2022 16:36:13 +0900 Subject: [PATCH] Fixed read error in inconsistent csv header (#16) --- .../CsvHelper.FastDynamic.Tests.csproj | 2 +- CsvHelper.FastDynamic.Tests/CsvReaderTests.cs | 77 +++++++++++++++---- CsvHelper.FastDynamic.Tests/TestData.cs | 2 + CsvHelper.FastDynamic/CsvReaderExtensions.cs | 10 +-- 4 files changed, 68 insertions(+), 23 deletions(-) diff --git a/CsvHelper.FastDynamic.Tests/CsvHelper.FastDynamic.Tests.csproj b/CsvHelper.FastDynamic.Tests/CsvHelper.FastDynamic.Tests.csproj index 12efe8b..2f46f20 100644 --- a/CsvHelper.FastDynamic.Tests/CsvHelper.FastDynamic.Tests.csproj +++ b/CsvHelper.FastDynamic.Tests/CsvHelper.FastDynamic.Tests.csproj @@ -7,7 +7,7 @@ - + all diff --git a/CsvHelper.FastDynamic.Tests/CsvReaderTests.cs b/CsvHelper.FastDynamic.Tests/CsvReaderTests.cs index 8783a2e..9643e0e 100644 --- a/CsvHelper.FastDynamic.Tests/CsvReaderTests.cs +++ b/CsvHelper.FastDynamic.Tests/CsvReaderTests.cs @@ -11,7 +11,7 @@ namespace CsvHelper.FastDynamic.Tests public class CsvReaderTests { [Fact] - public void ReadDynamicRecords_Member() + public void ReadDynamicRecords() { var csvReader = CreateInMemoryReader(); @@ -20,7 +20,7 @@ public void ReadDynamicRecords_Member() Assert.NotNull(records); Assert.Equal(3, records.Count); - for (int i = 0; i < 3; i++) + for (var i = 0; i < 3; i++) { Assert.Equal(TestData.CsvRecords[i]["Id"], records[i].Id); Assert.Equal(TestData.CsvRecords[i]["Name"], records[i].Name); @@ -29,7 +29,7 @@ public void ReadDynamicRecords_Member() } [Fact] - public void ReadDynamicRecords_Indexer() + public void ReadDynamicRecords_UseIndexer() { var csvReader = CreateInMemoryReader(); @@ -38,7 +38,7 @@ public void ReadDynamicRecords_Indexer() Assert.NotNull(records); Assert.Equal(3, records.Count); - for (int i = 0; i < 3; i++) + for (var i = 0; i < 3; i++) { Assert.Equal(TestData.CsvRecords[i]["Id"], records[i]["Id"]); Assert.Equal(TestData.CsvRecords[i]["Name"], records[i]["Name"]); @@ -47,7 +47,7 @@ public void ReadDynamicRecords_Indexer() } [Fact] - public void ReadDynamicRecords_Dictionary() + public void ReadDynamicRecords_AsDictionary() { var csvReader = CreateInMemoryReader(); @@ -58,7 +58,7 @@ public void ReadDynamicRecords_Dictionary() Assert.NotNull(records); Assert.Equal(3, records.Length); - for (int i = 0; i < 3; i++) + for (var i = 0; i < 3; i++) { Assert.Equal(TestData.CsvRecords[i]["Id"], records[i]["Id"]); Assert.Equal(TestData.CsvRecords[i]["Name"], records[i]["Name"]); @@ -66,6 +66,27 @@ public void ReadDynamicRecords_Dictionary() } } + [Fact] + public void ReadDynamicRecords_WithMissingHeader() + { + var csvReader = CreateInMemoryReader_WithMissingHeader(); + + var records = csvReader.GetDynamicRecords() + .Cast>() + .ToArray(); + + Assert.NotNull(records); + Assert.Equal(3, records.Length); + + for (var i = 0; i < 3; i++) + { + Assert.Equal(2, records[i].Count); + + Assert.Equal(TestData.CsvRecords[i]["Id"], records[i]["Id"]); + Assert.Equal(TestData.CsvRecords[i]["Name"], records[i]["Name"]); + } + } + [Fact] public async Task ReadDynamicRecordsAsync() { @@ -76,7 +97,7 @@ public async Task ReadDynamicRecordsAsync() Assert.NotNull(records); Assert.Equal(3, records.Count); - for (int i = 0; i < 3; i++) + for (var i = 0; i < 3; i++) { Assert.Equal(TestData.CsvRecords[i]["Id"], records[i].Id); Assert.Equal(TestData.CsvRecords[i]["Name"], records[i].Name); @@ -84,6 +105,27 @@ public async Task ReadDynamicRecordsAsync() } } + [Fact] + public async Task ReadDynamicRecordsAsync_WithMissingHeader() + { + var csvReader = CreateInMemoryReader_WithMissingHeader(); + + var records = (await csvReader.GetDynamicRecordsAsync()) + .Cast>() + .ToArray(); + + Assert.NotNull(records); + Assert.Equal(3, records.Length); + + for (var i = 0; i < 3; i++) + { + Assert.Equal(2, records[i].Count); + + Assert.Equal(TestData.CsvRecords[i]["Id"], records[i]["Id"]); + Assert.Equal(TestData.CsvRecords[i]["Name"], records[i]["Name"]); + } + } + [Fact] public void EnumerateDynamicRecords() { @@ -91,7 +133,7 @@ public void EnumerateDynamicRecords() var records = csvReader.EnumerateDynamicRecords(); - int count = 0; + var count = 0; foreach (var record in records) { @@ -115,7 +157,7 @@ public async Task EnumerateDynamicRecordsAsync() var records = csvReader.EnumerateDynamicRecordsAsync(); - int count = 0; + var count = 0; await foreach (var record in records) { @@ -139,12 +181,12 @@ public void AddDynamicColumns_Member() var records = csvReader.GetDynamicRecords(); - for (int i = 0; i < 3; i++) + for (var i = 0; i < 3; i++) { records[i].Append = $"test-{i}"; } - for (int i = 0; i < 3; i++) + for (var i = 0; i < 3; i++) { Assert.Equal(TestData.CsvRecords[i]["Id"], records[i].Id); Assert.Equal(TestData.CsvRecords[i]["Name"], records[i].Name); @@ -161,12 +203,12 @@ public void AddDynamicColumns_Indexer() var records = csvReader.GetDynamicRecords(); - for (int i = 0; i < 3; i++) + for (var i = 0; i < 3; i++) { records[i]["Append"] = $"test-{i}"; } - for (int i = 0; i < 3; i++) + for (var i = 0; i < 3; i++) { Assert.Equal(TestData.CsvRecords[i]["Id"], records[i]["Id"]); Assert.Equal(TestData.CsvRecords[i]["Name"], records[i]["Name"]); @@ -185,12 +227,12 @@ public void AddDynamicColumns_Dictionary() .Cast>() .ToArray(); - for (int i = 0; i < 3; i++) + for (var i = 0; i < 3; i++) { records[i]["Append"] = $"test-{i}"; } - for (int i = 0; i < 3; i++) + for (var i = 0; i < 3; i++) { Assert.Equal(TestData.CsvRecords[i]["Id"], records[i]["Id"]); Assert.Equal(TestData.CsvRecords[i]["Name"], records[i]["Name"]); @@ -204,5 +246,10 @@ private CsvReader CreateInMemoryReader() { return new CsvReader(new StringReader(TestData.CsvContent), CultureInfo.InvariantCulture); } + + private CsvReader CreateInMemoryReader_WithMissingHeader() + { + return new CsvReader(new StringReader(TestData.CsvContentWithMissingHeader), CultureInfo.InvariantCulture); + } } } diff --git a/CsvHelper.FastDynamic.Tests/TestData.cs b/CsvHelper.FastDynamic.Tests/TestData.cs index fdcabc4..c763681 100644 --- a/CsvHelper.FastDynamic.Tests/TestData.cs +++ b/CsvHelper.FastDynamic.Tests/TestData.cs @@ -6,6 +6,8 @@ public static class TestData { public static readonly string CsvContent = $"Id,Name,Location\r\n1,kazuakix,Wakayama\r\n2,daruyanagi,Ehime\r\n3,buchizo,Osaka\r\n"; + public static readonly string CsvContentWithMissingHeader = $"Id,Name\r\n1,kazuakix\r\n2,daruyanagi,Ehime\r\n3,buchizo\r\n"; + public static readonly IReadOnlyList> CsvRecords = new[] { new Dictionary { { "Id", "1" }, { "Name", "kazuakix" }, { "Location", "Wakayama" } }, diff --git a/CsvHelper.FastDynamic/CsvReaderExtensions.cs b/CsvHelper.FastDynamic/CsvReaderExtensions.cs index 9021b9e..200d4d0 100644 --- a/CsvHelper.FastDynamic/CsvReaderExtensions.cs +++ b/CsvHelper.FastDynamic/CsvReaderExtensions.cs @@ -7,8 +7,7 @@ namespace CsvHelper.FastDynamic { public static class CsvReaderExtensions { - public static IReadOnlyList GetDynamicRecords(this CsvReader csvReader) - => csvReader.EnumerateDynamicRecords().ToArray(); + public static IReadOnlyList GetDynamicRecords(this CsvReader csvReader) => csvReader.EnumerateDynamicRecords().ToArray(); public static IEnumerable EnumerateDynamicRecords(this CsvReader csvReader) { @@ -34,10 +33,7 @@ public static IEnumerable EnumerateDynamicRecords(this CsvReader csvRea { var values = new object[csvReader.HeaderRecord.Length]; - for (var i = 0; i < csvReader.HeaderRecord.Length; i++) - { - values[i] = csvReader.Parser[i]; - } + Array.Copy(csvReader.Parser.Record, values, csvReader.HeaderRecord.Length); record = new CsvRecord(csvHeader, values); } @@ -95,7 +91,7 @@ public static async IAsyncEnumerable EnumerateDynamicRecordsAsync(this { var values = new object[csvReader.HeaderRecord.Length]; - Array.Copy(csvReader.Parser.Record, values, csvReader.Parser.Record.Length); + Array.Copy(csvReader.Parser.Record, values, csvReader.HeaderRecord.Length); record = new CsvRecord(csvHeader, values); }