Skip to content

Commit 3af32d5

Browse files
authored
Merge pull request apache#606 from OldTruckDriver/fix/csvprinter-reader-quote-escape
[CSV-326] Escape Reader values with quote and escape
2 parents 2712665 + d80a832 commit 3af32d5

3 files changed

Lines changed: 22 additions & 3 deletions

File tree

src/changes/changes.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
<action type="fix" dev="ggregory" due-to="Ruiqi Dong, Gary Gregory" issue="CSV-322">CSVFormat.Builder.setQuote() does not refresh quotedNullString (#2447).</action>
5252
<action type="fix" dev="ggregory" due-to="Ruiqi Dong, Gary Gregory" issue="CSV-324">Lexer.isDelimiter() accepts a partial multi-character delimiter at EOF (#603).</action>
5353
<action type="fix" dev="ggregory" due-to="Ruiqi Dong, Gary Gregory" issue="CSV-325">CSVParser applies characterOffset to bytePosition (#604).</action>
54+
<action type="fix" dev="ggregory" due-to="Ruiqi Dong, Gary Gregory" issue="CSV-326">CSVPrinter Reader printing with quote and escape can emit CSV that its parser cannot read back.</action>
5455
<action type="fix" dev="ggregory" due-to="Ruiqi Dong, Gary Gregory" issue="CSV-327">CSVParser applies maxRows to record numbers instead of rows produced when setRecordNumber(...) is used.</action>
5556
<!-- ADD -->
5657
<action type="add" dev="ggregory" due-to="Gary Gregory, Indy, Sylvia van Os" issue="CSV-307">Add an "Android Compatibility" section to the web site.</action>

src/main/java/org/apache/commons/csv/CSVFormat.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2522,14 +2522,15 @@ private void printWithQuotes(final Reader reader, final Appendable appendable) t
25222522
return;
25232523
}
25242524
final char quote = getQuoteCharacter().charValue(); // Explicit unboxing is intentional
2525+
final char escape = isEscapeCharacterSet() ? getEscapeChar() : quote;
25252526
// (1) Append opening quote
25262527
append(quote, appendable);
2527-
// (2) Append Reader contents, doubling quotes
2528+
// (2) Append Reader contents, doubling quotes and escape characters
25282529
int c;
25292530
while (EOF != (c = reader.read())) {
25302531
append((char) c, appendable);
2531-
if (c == quote) {
2532-
append(quote, appendable);
2532+
if (c == quote || c == escape) {
2533+
append((char) c, appendable);
25332534
}
25342535
}
25352536
// (3) Append closing quote

src/test/java/org/apache/commons/csv/CSVFormatTest.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -966,6 +966,23 @@ void testPrintWithQuotes() throws IOException {
966966
assertEquals("\"\"\"a,b,c\r\nx,y,z\"", out.toString());
967967
}
968968

969+
/**
970+
* Tests <a href="https://issues.apache.org/jira/browse/CSV-326">CSV-326</a>.
971+
*/
972+
@Test
973+
void testPrintWithQuotesEscapeBeforeQuote() throws IOException {
974+
final CSVFormat format = CSVFormat.DEFAULT.builder()
975+
.setEscape('\\')
976+
.setQuote('"')
977+
.get();
978+
final String value = "\\\"";
979+
final Appendable out = new StringBuilder();
980+
format.print(new StringReader(value), out, true);
981+
try (CSVParser parser = CSVParser.parse(out.toString(), format)) {
982+
assertEquals(value, parser.getRecords().get(0).get(0));
983+
}
984+
}
985+
969986
@Test
970987
void testQuoteCharSameAsCommentStartThrowsException() {
971988
assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.builder().setQuote('!').setCommentMarker('!').get());

0 commit comments

Comments
 (0)