Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/changes/changes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
<action type="fix" dev="ggregory" due-to="Ruiqi Dong, Gary Gregory" issue="CSV-322">CSVFormat.Builder.setQuote() does not refresh quotedNullString (#2447).</action>
<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>
<action type="fix" dev="ggregory" due-to="Ruiqi Dong, Gary Gregory" issue="CSV-325">CSVParser applies characterOffset to bytePosition (#604).</action>
<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>
<!-- ADD -->
<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>
<action type="add" dev="ggregory" due-to="Ruiqi Dong, Gary Gregory" issue="CSV-325">Add CSVParser.Builder.setByteOffset(long) (#604).</action>
Expand Down
7 changes: 4 additions & 3 deletions src/main/java/org/apache/commons/csv/CSVFormat.java
Original file line number Diff line number Diff line change
Expand Up @@ -2522,14 +2522,15 @@ private void printWithQuotes(final Reader reader, final Appendable appendable) t
return;
}
final char quote = getQuoteCharacter().charValue(); // Explicit unboxing is intentional
final char escape = isEscapeCharacterSet() ? getEscapeChar() : quote;
// (1) Append opening quote
append(quote, appendable);
// (2) Append Reader contents, doubling quotes
// (2) Append Reader contents, doubling quotes and escape characters
int c;
while (EOF != (c = reader.read())) {
append((char) c, appendable);
if (c == quote) {
append(quote, appendable);
if (c == quote || c == escape) {
append((char) c, appendable);
}
}
// (3) Append closing quote
Expand Down
17 changes: 17 additions & 0 deletions src/test/java/org/apache/commons/csv/CSVFormatTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -966,6 +966,23 @@ void testPrintWithQuotes() throws IOException {
assertEquals("\"\"\"a,b,c\r\nx,y,z\"", out.toString());
}

/**
* Tests <a href="https://issues.apache.org/jira/browse/CSV-326">CSV-326</a>.
*/
@Test
void testPrintWithQuotesEscapeBeforeQuote() throws IOException {
final CSVFormat format = CSVFormat.DEFAULT.builder()
.setEscape('\\')
.setQuote('"')
.get();
final String value = "\\\"";
final Appendable out = new StringBuilder();
format.print(new StringReader(value), out, true);
try (CSVParser parser = CSVParser.parse(out.toString(), format)) {
assertEquals(value, parser.getRecords().get(0).get(0));
}
}

@Test
void testQuoteCharSameAsCommentStartThrowsException() {
assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.builder().setQuote('!').setCommentMarker('!').get());
Expand Down