From a99f2609299a72b08a3e43c2968822555528da4e Mon Sep 17 00:00:00 2001 From: rootvector2 Date: Mon, 15 Jun 2026 21:31:34 +0530 Subject: [PATCH 1/2] quote value starting with comment marker in minimal quote mode --- .../java/org/apache/commons/csv/CSVFormat.java | 5 +++-- .../org/apache/commons/csv/CSVPrinterTest.java | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/apache/commons/csv/CSVFormat.java b/src/main/java/org/apache/commons/csv/CSVFormat.java index 03211e689..4f60eff93 100644 --- a/src/main/java/org/apache/commons/csv/CSVFormat.java +++ b/src/main/java/org/apache/commons/csv/CSVFormat.java @@ -2454,10 +2454,11 @@ private void printWithQuotes(final Object object, final CharSequence charSeq, fi } } else { char c = charSeq.charAt(pos); - if (c <= Constants.COMMENT) { + if (c <= Constants.COMMENT || isCommentMarkerSet() && c == commentMarker.charValue()) { // Some other chars at the start of a value caused the parser to fail, so for now // encapsulate if we start in anything less than '#'. We are being conservative - // by including the default comment char too. + // by including the default comment char and any configured comment marker too, + // which the parser would otherwise read back as a comment line. quote = true; } else { while (pos < len) { diff --git a/src/test/java/org/apache/commons/csv/CSVPrinterTest.java b/src/test/java/org/apache/commons/csv/CSVPrinterTest.java index 16901c4e2..e00accfb0 100644 --- a/src/test/java/org/apache/commons/csv/CSVPrinterTest.java +++ b/src/test/java/org/apache/commons/csv/CSVPrinterTest.java @@ -1829,6 +1829,24 @@ void testQuoteCommaFirstChar() throws IOException { } } + @Test + void testQuoteCommentMarkerFirstChar() throws IOException { + final CSVFormat format = CSVFormat.DEFAULT.builder().setCommentMarker(';').get(); + final StringWriter sw = new StringWriter(); + final String col1 = ";comment-like"; + try (CSVPrinter printer = new CSVPrinter(sw, format)) { + printer.printRecord(col1, "b"); + } + assertEquals("\";comment-like\",b" + RECORD_SEPARATOR, sw.toString()); + // A value starting with the comment marker must read back as data, not a dropped comment line. + try (CSVParser parser = CSVParser.parse(sw.toString(), format)) { + final List records = parser.getRecords(); + assertEquals(1, records.size()); + assertEquals(col1, records.get(0).get(0)); + assertEquals("b", records.get(0).get(1)); + } + } + @Test void testQuoteNonNumeric() throws IOException { final StringWriter sw = new StringWriter(); From 3c2291cf5e40c5b9a19f3a6b3165fb27c8de5321 Mon Sep 17 00:00:00 2001 From: rootvector2 Date: Tue, 16 Jun 2026 14:35:39 +0530 Subject: [PATCH 2/2] expand comment marker test to contrast printed comment with quoted value --- .../org/apache/commons/csv/CSVPrinterTest.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/test/java/org/apache/commons/csv/CSVPrinterTest.java b/src/test/java/org/apache/commons/csv/CSVPrinterTest.java index e00accfb0..f4f3c85b1 100644 --- a/src/test/java/org/apache/commons/csv/CSVPrinterTest.java +++ b/src/test/java/org/apache/commons/csv/CSVPrinterTest.java @@ -1835,15 +1835,24 @@ void testQuoteCommentMarkerFirstChar() throws IOException { final StringWriter sw = new StringWriter(); final String col1 = ";comment-like"; try (CSVPrinter printer = new CSVPrinter(sw, format)) { + // A real comment is written with the marker, unquoted. + printer.printComment("a real comment"); + // A value starting with the marker is quoted, so it does not read back as a comment. printer.printRecord(col1, "b"); + // The marker past the first character does not start a comment, so only the leading-marker value is quoted. + printer.printRecord("a;b", ";c"); } - assertEquals("\";comment-like\",b" + RECORD_SEPARATOR, sw.toString()); - // A value starting with the comment marker must read back as data, not a dropped comment line. + assertEquals("; a real comment" + RECORD_SEPARATOR + + "\";comment-like\",b" + RECORD_SEPARATOR + + "a;b,\";c\"" + RECORD_SEPARATOR, sw.toString()); + // The comment is dropped on read; both data records survive intact. try (CSVParser parser = CSVParser.parse(sw.toString(), format)) { final List records = parser.getRecords(); - assertEquals(1, records.size()); + assertEquals(2, records.size()); assertEquals(col1, records.get(0).get(0)); assertEquals("b", records.get(0).get(1)); + assertEquals("a;b", records.get(1).get(0)); + assertEquals(";c", records.get(1).get(1)); } }