Skip to content

Round-trip CSV exports that contain line breaks, commas or quotes - #154

Merged
matt-edmondson merged 3 commits into
mainfrom
fix/149-csv-round-trip
Sep 26, 2026
Merged

matt-edmondson merged 3 commits into
mainfrom
fix/149-csv-round-trip

Conversation

@matt-edmondson

@matt-edmondson matt-edmondson commented Sep 26, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #149

Summary

Export and Import disagreed on the CSV format. Export quoted only Description and KnownPaths, and Import read the file with File.ReadAllLines. A multi-paragraph description was cut off at its first line break, and a suggested name like dog, cat.jpg dropped the whole row.

  • Export: BuildCsv (extracted from ExportCsv) quotes and escapes every field. It formats dates and sizes with the invariant culture.
  • Import: ParseCsv (extracted from ImportCsv) reads the whole text through a new RFC 4180 ParseCsvRecords, so quoted fields can hold commas, doubled quotes and line breaks. "Skipping line N" messages still name the line each record starts on, and blank lines are still ignored.
  • ParseCsvLine keeps its signature and existing behaviour; it now delegates to the record parser.

Files exported by earlier versions still import: bare fields parse as before.

Test

  • CsvExportThenImportRoundTripsEveryField runs BuildCsv then ParseCsv on three entries: a multi-paragraph description with doubled quotes, a suggested name with a comma and an apostrophe plus a CRLF description, and multiple known paths. It checks every field. (The suggested name avoids ", which Windows doesn't allow in file names; quote escaping is covered by the description.)
  • ParseCsvRecordsKeepsLineBreaksInsideQuotedFields covers CRLF, blank lines, embedded newlines, escaped quotes and start-line numbers.

With the old export quoting and line-by-line import restored, the round-trip test fails (3 entries in, fewer out). With the fix, the full suite passes 39/39.

This branch also merges cleanly with #152 and #153.

🤖 Generated with Claude Code

https://claude.ai/code/session_0113g7mUxeizhTrH6na279Ez

Export quoted only Description and KnownPaths, and Import read the file with
File.ReadAllLines, so a multi-paragraph description was truncated at its first
line break and a suggested name containing a comma dropped the whole row.

Export now quotes every field, and Import parses the whole file as RFC 4180
records, so quoted fields may span lines. Skipped-row messages still report the
line the record starts on.

Fixes #149

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0113g7mUxeizhTrH6na279Ez
A double quote is not a valid Windows file-name character, so FileName
rejected the test's own fixture on the Windows leg. The name keeps the comma
and gains an apostrophe; quote escaping is still covered by the description.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0113g7mUxeizhTrH6na279Ez
SonarCloud flagged ParseCsvRecords for cognitive complexity (17, limit 15) and
for advancing the for-loop counter inside the body. Reading a quoted field now
lives in ReadQuotedField, and the scan is a while loop. Behaviour is unchanged.

Also switch the new tests to Assert.HasCount and Assert.AreSequenceEqual, as
the MSTest analyzers suggest.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0113g7mUxeizhTrH6na279Ez
@sonarqubecloud

Copy link
Copy Markdown

@matt-edmondson
matt-edmondson merged commit 55d9d48 into main Sep 26, 2026
12 checks passed
@matt-edmondson
matt-edmondson deleted the fix/149-csv-round-trip branch September 26, 2026 09:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CSV export → import loses data: multi-paragraph descriptions are truncated and names with commas drop the row

2 participants