@@ -188,6 +188,14 @@ private Connection getH2Connection() throws SQLException, ClassNotFoundException
188188 return DriverManager .getConnection ("jdbc:h2:mem:my_test;" , "sa" , "" );
189189 }
190190
191+ private String printNullRecord (final CSVFormat format ) throws IOException {
192+ final StringWriter sw = new StringWriter ();
193+ try (CSVPrinter printer = new CSVPrinter (sw , format )) {
194+ printer .printRecord ((Object ) null );
195+ }
196+ return sw .toString ();
197+ }
198+
191199 private CSVPrinter printWithHeaderComments (final StringWriter sw , final Date now , final CSVFormat baseFormat ) throws IOException {
192200 // Use withHeaderComments first to test CSV-145
193201 // @formatter:off
@@ -1721,6 +1729,31 @@ void testPrinter7() throws IOException {
17211729 }
17221730 }
17231731
1732+ @ Test
1733+ void testPrintNullValueStartingRecord () throws IOException {
1734+ final StringWriter sw = new StringWriter ();
1735+ try (CSVPrinter printer = new CSVPrinter (sw , CSVFormat .DEFAULT )) {
1736+ printer .printRecord ("a" );
1737+ printer .printRecord ((Object ) null );
1738+ printer .printRecord ("b" );
1739+ }
1740+ final String csv = sw .toString ();
1741+ assertEquals ("a" + RECORD_SEPARATOR + "\" \" " + RECORD_SEPARATOR + "b" + RECORD_SEPARATOR , csv );
1742+ try (CSVParser parser = CSVParser .parse (csv , CSVFormat .DEFAULT )) {
1743+ final List <CSVRecord > records = parser .getRecords ();
1744+ assertEquals (3 , records .size ());
1745+ assertArrayEquals (new String [] { "" }, records .get (1 ).values ());
1746+ }
1747+ // An explicit MINIMAL quote mode encapsulates it too.
1748+ assertEquals ("\" \" " + RECORD_SEPARATOR , printNullRecord (CSVFormat .DEFAULT .builder ().setQuoteMode (QuoteMode .MINIMAL ).get ()));
1749+ // ALL encodes null as the bare empty field, distinct from a quoted empty string (CSV-203).
1750+ assertEquals (RECORD_SEPARATOR , printNullRecord (CSVFormat .DEFAULT .builder ().setQuoteMode (QuoteMode .ALL ).get ()));
1751+ // ALL_NON_NULL encodes null as the bare empty field, so it must stay unquoted.
1752+ assertEquals (RECORD_SEPARATOR , printNullRecord (CSVFormat .DEFAULT .builder ().setQuoteMode (QuoteMode .ALL_NON_NULL ).get ()));
1753+ // Without a quote character there is nothing to encapsulate with.
1754+ assertEquals (RECORD_SEPARATOR , printNullRecord (CSVFormat .DEFAULT .builder ().setQuote (null ).get ()));
1755+ }
1756+
17241757 @ Test
17251758 void testPrintNullValues () throws IOException {
17261759 final StringWriter sw = new StringWriter ();
@@ -1854,8 +1887,9 @@ void testPrintRecordsWithObjectArray() throws IOException {
18541887 printer .printRecords (objectArray );
18551888 assertEquals (objectArray .length , printer .getRecordCount ());
18561889 }
1857- assertEquals (6 , charArrayWriter .size ());
1858- assertEquals ("\n \n \n \n \n \n " , charArrayWriter .toString ());
1890+ final String expected = "\" \" \n \" \" \n \" \" \n \n \" \" \n \" \" \n " ;
1891+ assertEquals (expected .length (), charArrayWriter .size ());
1892+ assertEquals (expected , charArrayWriter .toString ());
18591893 }
18601894
18611895 @ Test
0 commit comments