Skip to content

Commit ce08e8c

Browse files
[CSV-328] Fix quoted null string after disabling quote
setNullString(String) rebuilt quotedNullString by concatenating the nullable quoteCharacter field directly, so calling setQuote(null) before setNullString(...) produced a literal "nullNULLnull". Extract a shared setQuotedNullString() helper that applies the default-quote fallback, so both builder orders produce the same state. Reviewed-by: OpenAI Codex Reviewed-by: Anthropic Claude Code
1 parent ed8dbf2 commit ce08e8c

3 files changed

Lines changed: 12 additions & 2 deletions

File tree

src/changes/changes.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
<action type="fix" dev="ggregory" due-to="Ruiqi Dong, Gary Gregory" issue="CSV-325">CSVParser applies characterOffset to bytePosition (#604).</action>
5454
<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>
5555
<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>
56+
<action type="fix" dev="ggregory" due-to="Ruiqi Dong, Gary Gregory" issue="CSV-328">CSVFormat.Builder.setNullString(String) can build an invalid quoted null string after setQuote(null).</action>
5657
<action type="fix" dev="ggregory" due-to="OldTruckDriver, Gary Gregory" issue="CSV-326">Escape Reader values with quote and escape (#606).</action>
5758
<action type="fix" dev="ggregory" due-to="Dexter.k, Gary Gregory">Clear escape delimiter buffer before peek in Lexer.isEscapeDelimiter() (#608, #611).</action>
5859
<action type="fix" dev="ggregory" due-to="Dexter.k, Gary Gregory">Escape quote char in printWithEscapes when QuoteMode is NONE (#609).</action>

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -780,7 +780,7 @@ public Builder setMaxRows(final long maxRows) {
780780
*/
781781
public Builder setNullString(final String nullString) {
782782
this.nullString = nullString;
783-
this.quotedNullString = quoteCharacter + nullString + quoteCharacter;
783+
setQuotedNullString();
784784
return this;
785785
}
786786

@@ -806,9 +806,13 @@ public Builder setQuote(final Character quoteCharacter) {
806806
throw new IllegalArgumentException("The quoteCharacter cannot be a line break");
807807
}
808808
this.quoteCharacter = quoteCharacter;
809+
setQuotedNullString();
810+
return this;
811+
}
812+
813+
private void setQuotedNullString() {
809814
final Character quote = quoteCharacter != null ? quoteCharacter : Constants.DOUBLE_QUOTE_CHAR;
810815
this.quotedNullString = quote + nullString + quote;
811-
return this;
812816
}
813817

814818
/**

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,6 +1040,11 @@ void testQuotedNullStringTracksQuoteCharacter() throws IOException {
10401040
builder.setQuote((Character) null);
10411041
builder.get().print(null, out, true);
10421042
assertEquals("\"NULL\"", out.toString());
1043+
// reset, reverse setter order
1044+
out.setLength(0);
1045+
builder.setNullString(null).setQuote((Character) null).setNullString("NULL");
1046+
builder.get().print(null, out, true);
1047+
assertEquals("\"NULL\"", out.toString());
10431048
}
10441049

10451050
@Test

0 commit comments

Comments
 (0)