View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.csv;
19  
20  import static org.apache.commons.csv.Constants.BACKSLASH;
21  import static org.apache.commons.csv.Constants.CR;
22  import static org.junit.jupiter.api.Assertions.assertArrayEquals;
23  import static org.junit.jupiter.api.Assertions.assertEquals;
24  import static org.junit.jupiter.api.Assertions.assertFalse;
25  import static org.junit.jupiter.api.Assertions.assertNotEquals;
26  import static org.junit.jupiter.api.Assertions.assertNull;
27  import static org.junit.jupiter.api.Assertions.assertThrows;
28  import static org.mockito.Mockito.mock;
29  import static org.mockito.Mockito.never;
30  import static org.mockito.Mockito.times;
31  import static org.mockito.Mockito.verify;
32  
33  import java.io.CharArrayWriter;
34  import java.io.File;
35  import java.io.FileReader;
36  import java.io.IOException;
37  import java.io.PrintStream;
38  import java.io.Reader;
39  import java.io.StringReader;
40  import java.io.StringWriter;
41  import java.io.Writer;
42  import java.nio.charset.Charset;
43  import java.nio.charset.StandardCharsets;
44  import java.sql.BatchUpdateException;
45  import java.sql.Connection;
46  import java.sql.DriverManager;
47  import java.sql.ResultSet;
48  import java.sql.SQLException;
49  import java.sql.Statement;
50  import java.util.Arrays;
51  import java.util.Date;
52  import java.util.HashSet;
53  import java.util.Iterator;
54  import java.util.LinkedList;
55  import java.util.List;
56  import java.util.Objects;
57  import java.util.Random;
58  import java.util.Vector;
59  
60  import org.apache.commons.io.FileUtils;
61  import org.apache.commons.io.output.NullOutputStream;
62  import org.apache.commons.lang3.StringUtils;
63  import org.h2.tools.SimpleResultSet;
64  import org.junit.jupiter.api.Disabled;
65  import org.junit.jupiter.api.Test;
66  
67  /**
68   * Tests {@link CSVPrinter}.
69   */
70  public class CSVPrinterTest {
71  
72      private static final char DQUOTE_CHAR = '"';
73      private static final char EURO_CH = '\u20AC';
74      private static final int ITERATIONS_FOR_RANDOM_TEST = 50000;
75      private static final char QUOTE_CH = '\'';
76  
77      private static String printable(final String s) {
78          final StringBuilder sb = new StringBuilder();
79          for (int i = 0; i < s.length(); i++) {
80              final char ch = s.charAt(i);
81              if (ch <= ' ' || ch >= 128) {
82                  sb.append("(").append((int) ch).append(")");
83              } else {
84                  sb.append(ch);
85              }
86          }
87          return sb.toString();
88      }
89  
90      private String longText2;
91  
92      private final String recordSeparator = CSVFormat.DEFAULT.getRecordSeparator();
93  
94      private void doOneRandom(final CSVFormat format) throws Exception {
95          final Random r = new Random();
96  
97          final int nLines = r.nextInt(4) + 1;
98          final int nCol = r.nextInt(3) + 1;
99          // nLines=1;nCol=2;
100         final String[][] lines = generateLines(nLines, nCol);
101 
102         final StringWriter sw = new StringWriter();
103         try (final CSVPrinter printer = new CSVPrinter(sw, format)) {
104 
105             for (int i = 0; i < nLines; i++) {
106                 // for (int j=0; j<lines[i].length; j++) System.out.println("### VALUE=:" + printable(lines[i][j]));
107                 printer.printRecord((Object[]) lines[i]);
108             }
109 
110             printer.flush();
111         }
112         final String result = sw.toString();
113         // System.out.println("### :" + printable(result));
114 
115         try (final CSVParser parser = CSVParser.parse(result, format)) {
116             final List<CSVRecord> parseResult = parser.getRecords();
117 
118             final String[][] expected = lines.clone();
119             for (int i = 0; i < expected.length; i++) {
120                 expected[i] = expectNulls(expected[i], format);
121             }
122             Utils.compare("Printer output :" + printable(result), expected, parseResult);
123         }
124     }
125 
126     private void doRandom(final CSVFormat format, final int iter) throws Exception {
127         for (int i = 0; i < iter; i++) {
128             doOneRandom(format);
129         }
130     }
131 
132     /**
133      * Converts an input CSV array into expected output values WRT NULLs. NULL strings are converted to null values
134      * because the parser will convert these strings to null.
135      */
136     private <T> T[] expectNulls(final T[] original, final CSVFormat csvFormat) {
137         final T[] fixed = original.clone();
138         for (int i = 0; i < fixed.length; i++) {
139             if (Objects.equals(csvFormat.getNullString(), fixed[i])) {
140                 fixed[i] = null;
141             }
142         }
143         return fixed;
144     }
145 
146     private String[][] generateLines(final int nLines, final int nCol) {
147         final String[][] lines = new String[nLines][];
148         for (int i = 0; i < nLines; i++) {
149             final String[] line = new String[nCol];
150             lines[i] = line;
151             for (int j = 0; j < nCol; j++) {
152                 line[j] = randStr();
153             }
154         }
155         return lines;
156     }
157 
158     private Connection getH2Connection() throws SQLException, ClassNotFoundException {
159         Class.forName("org.h2.Driver");
160         return DriverManager.getConnection("jdbc:h2:mem:my_test;", "sa", "");
161     }
162 
163     private CSVPrinter printWithHeaderComments(final StringWriter sw, final Date now, final CSVFormat baseFormat)
164             throws IOException {
165         // Use withHeaderComments first to test CSV-145
166         // @formatter:off
167         final CSVFormat format = baseFormat.builder()
168                 .setHeaderComments("Generated by Apache Commons CSV 1.1", now)
169                 .setCommentMarker('#')
170                 .setHeader("Col1", "Col2")
171                 .build();
172         // @formatter:on
173         final CSVPrinter csvPrinter = format.print(sw);
174         csvPrinter.printRecord("A", "B");
175         csvPrinter.printRecord("C", "D");
176         csvPrinter.close();
177         return csvPrinter;
178     }
179 
180     private String randStr() {
181         final Random r = new Random();
182 
183         final int sz = r.nextInt(20);
184         // sz = r.nextInt(3);
185         final char[] buf = new char[sz];
186         for (int i = 0; i < sz; i++) {
187             // stick in special chars with greater frequency
188             final char ch;
189             final int what = r.nextInt(20);
190             switch (what) {
191             case 0:
192                 ch = '\r';
193                 break;
194             case 1:
195                 ch = '\n';
196                 break;
197             case 2:
198                 ch = '\t';
199                 break;
200             case 3:
201                 ch = '\f';
202                 break;
203             case 4:
204                 ch = ' ';
205                 break;
206             case 5:
207                 ch = ',';
208                 break;
209             case 6:
210                 ch = DQUOTE_CHAR;
211                 break;
212             case 7:
213                 ch = '\'';
214                 break;
215             case 8:
216                 ch = BACKSLASH;
217                 break;
218             default:
219                 ch = (char) r.nextInt(300);
220                 break;
221             // default: ch = 'a'; break;
222             }
223             buf[i] = ch;
224         }
225         return new String(buf);
226     }
227 
228     private void setUpTable(final Connection connection) throws SQLException {
229         try (final Statement statement = connection.createStatement()) {
230             statement.execute("CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255), TEXT CLOB)");
231             statement.execute("insert into TEST values(1, 'r1', 'long text 1')");
232             longText2 = StringUtils.repeat('a', IOUtils.DEFAULT_BUFFER_SIZE - 4);
233             longText2 += "\"\r\n\"a\"";
234             longText2 += StringUtils.repeat('a', IOUtils.DEFAULT_BUFFER_SIZE - 1);
235             statement.execute("insert into TEST values(2, 'r2', '" + longText2 + "')");
236             longText2 = longText2.replace("\"","\"\"");
237         }
238     }
239 
240     @Test
241     public void testCloseBackwardCompatibility() throws IOException {
242         try (final Writer writer = mock(Writer.class)) {
243             final CSVFormat csvFormat = CSVFormat.DEFAULT;
244             try (CSVPrinter csvPrinter = new CSVPrinter(writer, csvFormat)) {
245                 // empty
246             }
247             verify(writer, never()).flush();
248             verify(writer, times(1)).close();
249         }}
250 
251     @Test
252     public void testCloseWithCsvFormatAutoFlushOff() throws IOException {
253         try (final Writer writer = mock(Writer.class)) {
254             final CSVFormat csvFormat = CSVFormat.DEFAULT.withAutoFlush(false);
255             try (CSVPrinter csvPrinter = new CSVPrinter(writer, csvFormat)) {
256                 // empty
257             }
258             verify(writer, never()).flush();
259             verify(writer, times(1)).close();
260         }
261     }
262 
263     @Test
264     public void testCloseWithCsvFormatAutoFlushOn() throws IOException {
265         // System.out.println("start method");
266         try (final Writer writer = mock(Writer.class)) {
267             final CSVFormat csvFormat = CSVFormat.DEFAULT.withAutoFlush(true);
268             try (CSVPrinter csvPrinter = new CSVPrinter(writer, csvFormat)) {
269                 // empty
270             }
271             verify(writer, times(1)).flush();
272             verify(writer, times(1)).close();
273         }}
274 
275     @Test
276     public void testCloseWithFlushOff() throws IOException {
277         try (final Writer writer = mock(Writer.class)) {
278             final CSVFormat csvFormat = CSVFormat.DEFAULT;
279             @SuppressWarnings("resource")
280             final CSVPrinter csvPrinter = new CSVPrinter(writer, csvFormat);
281             csvPrinter.close(false);
282             verify(writer, never()).flush();
283             verify(writer, times(1)).close();
284         }
285     }
286 
287     @Test
288     public void testCloseWithFlushOn() throws IOException {
289         try (final Writer writer = mock(Writer.class)) {
290             @SuppressWarnings("resource")
291             final CSVPrinter csvPrinter = new CSVPrinter(writer, CSVFormat.DEFAULT);
292             csvPrinter.close(true);
293             verify(writer, times(1)).flush();
294         }
295     }
296 
297     @Test
298     public void testCRComment() throws IOException {
299         final StringWriter sw = new StringWriter();
300         final Object value = "abc";
301         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withCommentMarker('#'))) {
302             printer.print(value);
303             printer.printComment("This is a comment\r\non multiple lines\rthis is next comment\r");
304             assertEquals("abc" + recordSeparator + "# This is a comment" + recordSeparator + "# on multiple lines"
305                         + recordSeparator + "# this is next comment" + recordSeparator + "# " + recordSeparator, sw.toString());
306         }
307     }
308 
309     @Test
310     public void testCSV135() throws IOException {
311         final List<String> list = new LinkedList<>();
312         list.add("\"\"");   // ""
313         list.add("\\\\");   // \\
314         list.add("\\\"\\"); // \"\
315         //
316         // "",\\,\"\ (unchanged)
317         tryFormat(list, null, null, "\"\",\\\\,\\\"\\");
318         //
319         // """""",\\,"\""\" (quoted, and embedded DQ doubled)
320         tryFormat(list, '"',  null, "\"\"\"\"\"\",\\\\,\"\\\"\"\\\"");
321         //
322         // "",\\\\,\\"\\ (escapes escaped, not quoted)
323         tryFormat(list, null, '\\', "\"\",\\\\\\\\,\\\\\"\\\\");
324         //
325         // "\"\"","\\\\","\\\"\\" (quoted, and embedded DQ & escape escaped)
326         tryFormat(list, '"',  '\\', "\"\\\"\\\"\",\"\\\\\\\\\",\"\\\\\\\"\\\\\"");
327         //
328         // """""",\\,"\""\" (quoted, embedded DQ escaped)
329         tryFormat(list, '"',  '"',  "\"\"\"\"\"\",\\\\,\"\\\"\"\\\"");
330     }
331 
332     @Test
333     public void testCSV259() throws IOException {
334         final StringWriter sw = new StringWriter();
335         try (final Reader reader = new FileReader("src/test/resources/org/apache/commons/csv/CSV-259/sample.txt");
336                 final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withEscape('!').withQuote(null))) {
337             printer.print(reader);
338             assertEquals("x!,y!,z", sw.toString());
339         }
340     }
341 
342     @Test
343     public void testDelimeterQuoted() throws IOException {
344         final StringWriter sw = new StringWriter();
345         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote('\''))) {
346             printer.print("a,b,c");
347             printer.print("xyz");
348             assertEquals("'a,b,c',xyz", sw.toString());
349         }
350     }
351 
352     @Test
353     public void testDelimeterQuoteNone() throws IOException {
354         final StringWriter sw = new StringWriter();
355         final CSVFormat format = CSVFormat.DEFAULT.withEscape('!').withQuoteMode(QuoteMode.NONE);
356         try (final CSVPrinter printer = new CSVPrinter(sw, format)) {
357             printer.print("a,b,c");
358             printer.print("xyz");
359             assertEquals("a!,b!,c,xyz", sw.toString());
360         }
361     }
362 
363     @Test
364     public void testDelimeterStringQuoted() throws IOException {
365         final StringWriter sw = new StringWriter();
366         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.builder().setDelimiter("[|]").setQuote('\'').build())) {
367             printer.print("a[|]b[|]c");
368             printer.print("xyz");
369             assertEquals("'a[|]b[|]c'[|]xyz", sw.toString());
370         }
371     }
372 
373     @Test
374     public void testDelimeterStringQuoteNone() throws IOException {
375         final StringWriter sw = new StringWriter();
376         final CSVFormat format = CSVFormat.DEFAULT.builder().setDelimiter("[|]").setEscape('!').setQuoteMode(QuoteMode.NONE).build();
377         try (final CSVPrinter printer = new CSVPrinter(sw, format)) {
378             printer.print("a[|]b[|]c");
379             printer.print("xyz");
380             printer.print("a[xy]bc[]");
381             assertEquals("a![!|!]b![!|!]c[|]xyz[|]a[xy]bc[]", sw.toString());
382         }
383     }
384 
385     @Test
386     public void testDelimiterEscaped() throws IOException {
387         final StringWriter sw = new StringWriter();
388         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withEscape('!').withQuote(null))) {
389             printer.print("a,b,c");
390             printer.print("xyz");
391             assertEquals("a!,b!,c,xyz", sw.toString());
392         }
393     }
394 
395     @Test
396     public void testDelimiterPlain() throws IOException {
397         final StringWriter sw = new StringWriter();
398         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(null))) {
399             printer.print("a,b,c");
400             printer.print("xyz");
401             assertEquals("a,b,c,xyz", sw.toString());
402         }
403     }
404 
405     @Test
406     public void testDelimiterStringEscaped() throws IOException {
407         final StringWriter sw = new StringWriter();
408         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.builder().setDelimiter("|||").setEscape('!').setQuote(null).build())) {
409             printer.print("a|||b|||c");
410             printer.print("xyz");
411             assertEquals("a!|!|!|b!|!|!|c|||xyz", sw.toString());
412         }
413     }
414 
415     @Test
416     public void testDisabledComment() throws IOException {
417         final StringWriter sw = new StringWriter();
418         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT)) {
419             printer.printComment("This is a comment");
420             assertEquals("", sw.toString());
421         }
422     }
423 
424     @Test
425     public void testDontQuoteEuroFirstChar() throws IOException {
426         final StringWriter sw = new StringWriter();
427         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.RFC4180)) {
428             printer.printRecord(EURO_CH, "Deux");
429             assertEquals(EURO_CH + ",Deux" + recordSeparator, sw.toString());
430         }
431     }
432 
433     @Test
434     public void testEolEscaped() throws IOException {
435         final StringWriter sw = new StringWriter();
436         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(null).withEscape('!'))) {
437             printer.print("a\rb\nc");
438             printer.print("x\fy\bz");
439             assertEquals("a!rb!nc,x\fy\bz", sw.toString());
440         }
441     }
442 
443     @Test
444     public void testEolPlain() throws IOException {
445         final StringWriter sw = new StringWriter();
446         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(null))) {
447             printer.print("a\rb\nc");
448             printer.print("x\fy\bz");
449             assertEquals("a\rb\nc,x\fy\bz", sw.toString());
450         }
451     }
452 
453     @Test
454     public void testEolQuoted() throws IOException {
455         final StringWriter sw = new StringWriter();
456         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote('\''))) {
457             printer.print("a\rb\nc");
458             printer.print("x\by\fz");
459             assertEquals("'a\rb\nc',x\by\fz", sw.toString());
460         }
461     }
462 
463     @Test
464     public void testEscapeBackslash1() throws IOException {
465         final StringWriter sw = new StringWriter();
466         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(QUOTE_CH))) {
467             printer.print("\\");
468         }
469         assertEquals("\\", sw.toString());
470     }
471 
472     @Test
473     public void testEscapeBackslash2() throws IOException {
474         final StringWriter sw = new StringWriter();
475         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(QUOTE_CH))) {
476             printer.print("\\\r");
477         }
478         assertEquals("'\\\r'", sw.toString());
479     }
480 
481     @Test
482     public void testEscapeBackslash3() throws IOException {
483         final StringWriter sw = new StringWriter();
484         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(QUOTE_CH))) {
485             printer.print("X\\\r");
486         }
487         assertEquals("'X\\\r'", sw.toString());
488     }
489 
490     @Test
491     public void testEscapeBackslash4() throws IOException {
492         final StringWriter sw = new StringWriter();
493         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(QUOTE_CH))) {
494             printer.print("\\\\");
495         }
496         assertEquals("\\\\", sw.toString());
497     }
498 
499     @Test
500     public void testEscapeBackslash5() throws IOException {
501         final StringWriter sw = new StringWriter();
502         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(QUOTE_CH))) {
503             printer.print("\\\\");
504         }
505         assertEquals("\\\\", sw.toString());
506     }
507 
508     @Test
509     public void testEscapeNull1() throws IOException {
510         final StringWriter sw = new StringWriter();
511         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withEscape(null))) {
512             printer.print("\\");
513         }
514         assertEquals("\\", sw.toString());
515     }
516 
517     @Test
518     public void testEscapeNull2() throws IOException {
519         final StringWriter sw = new StringWriter();
520         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withEscape(null))) {
521             printer.print("\\\r");
522         }
523         assertEquals("\"\\\r\"", sw.toString());
524     }
525 
526     @Test
527     public void testEscapeNull3() throws IOException {
528         final StringWriter sw = new StringWriter();
529         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withEscape(null))) {
530             printer.print("X\\\r");
531         }
532         assertEquals("\"X\\\r\"", sw.toString());
533     }
534 
535     @Test
536     public void testEscapeNull4() throws IOException {
537         final StringWriter sw = new StringWriter();
538         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withEscape(null))) {
539             printer.print("\\\\");
540         }
541         assertEquals("\\\\", sw.toString());
542     }
543 
544     @Test
545     public void testEscapeNull5() throws IOException {
546         final StringWriter sw = new StringWriter();
547         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withEscape(null))) {
548             printer.print("\\\\");
549         }
550         assertEquals("\\\\", sw.toString());
551     }
552 
553     @Test
554     public void testExcelPrintAllArrayOfArrays() throws IOException {
555         final StringWriter sw = new StringWriter();
556         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL)) {
557             printer.printRecords((Object[]) new String[][] { { "r1c1", "r1c2" }, { "r2c1", "r2c2" } });
558             assertEquals("r1c1,r1c2" + recordSeparator + "r2c1,r2c2" + recordSeparator, sw.toString());
559         }
560     }
561 
562     @Test
563     public void testExcelPrintAllArrayOfLists() throws IOException {
564         final StringWriter sw = new StringWriter();
565         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL)) {
566             printer.printRecords(
567                     (Object[]) new List[] { Arrays.asList("r1c1", "r1c2"), Arrays.asList("r2c1", "r2c2") });
568             assertEquals("r1c1,r1c2" + recordSeparator + "r2c1,r2c2" + recordSeparator, sw.toString());
569         }
570     }
571 
572     @Test
573     public void testExcelPrintAllIterableOfArrays() throws IOException {
574         final StringWriter sw = new StringWriter();
575         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL)) {
576             printer.printRecords(Arrays.asList(new String[][] { { "r1c1", "r1c2" }, { "r2c1", "r2c2" } }));
577             assertEquals("r1c1,r1c2" + recordSeparator + "r2c1,r2c2" + recordSeparator, sw.toString());
578         }
579     }
580 
581     @Test
582     public void testExcelPrintAllIterableOfLists() throws IOException {
583         final StringWriter sw = new StringWriter();
584         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL)) {
585             printer.printRecords(
586                     Arrays.asList(Arrays.asList("r1c1", "r1c2"), Arrays.asList("r2c1", "r2c2")));
587             assertEquals("r1c1,r1c2" + recordSeparator + "r2c1,r2c2" + recordSeparator, sw.toString());
588         }
589     }
590 
591     @Test
592     public void testExcelPrinter1() throws IOException {
593         final StringWriter sw = new StringWriter();
594         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL)) {
595             printer.printRecord("a", "b");
596             assertEquals("a,b" + recordSeparator, sw.toString());
597         }
598     }
599 
600     @Test
601     public void testExcelPrinter2() throws IOException {
602         final StringWriter sw = new StringWriter();
603         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL)) {
604             printer.printRecord("a,b", "b");
605             assertEquals("\"a,b\",b" + recordSeparator, sw.toString());
606         }
607     }
608 
609     @Test
610     public void testHeader() throws IOException {
611         final StringWriter sw = new StringWriter();
612         try (final CSVPrinter printer = new CSVPrinter(sw,
613                 CSVFormat.DEFAULT.withQuote(null).withHeader("C1", "C2", "C3"))) {
614             printer.printRecord("a", "b", "c");
615             printer.printRecord("x", "y", "z");
616             assertEquals("C1,C2,C3\r\na,b,c\r\nx,y,z\r\n", sw.toString());
617         }
618     }
619 
620     @Test
621     public void testHeaderCommentExcel() throws IOException {
622         final StringWriter sw = new StringWriter();
623         final Date now = new Date();
624         final CSVFormat format = CSVFormat.EXCEL;
625         try (final CSVPrinter csvPrinter = printWithHeaderComments(sw, now, format)) {
626             assertEquals("# Generated by Apache Commons CSV 1.1\r\n# " + now + "\r\nCol1,Col2\r\nA,B\r\nC,D\r\n",
627                     sw.toString());
628         }
629     }
630 
631     @Test
632     public void testHeaderCommentTdf() throws IOException {
633         final StringWriter sw = new StringWriter();
634         final Date now = new Date();
635         final CSVFormat format = CSVFormat.TDF;
636         try (final CSVPrinter csvPrinter = printWithHeaderComments(sw, now, format)) {
637             assertEquals("# Generated by Apache Commons CSV 1.1\r\n# " + now + "\r\nCol1\tCol2\r\nA\tB\r\nC\tD\r\n",
638                     sw.toString());
639         }
640     }
641 
642     @Test
643     public void testHeaderNotSet() throws IOException {
644         final StringWriter sw = new StringWriter();
645         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(null))) {
646             printer.printRecord("a", "b", "c");
647             printer.printRecord("x", "y", "z");
648             assertEquals("a,b,c\r\nx,y,z\r\n", sw.toString());
649         }
650     }
651 
652     @Test
653     public void testInvalidFormat() {
654         assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withDelimiter(CR));
655     }
656 
657     @Test
658     public void testJdbcPrinter() throws IOException, ClassNotFoundException, SQLException {
659         final StringWriter sw = new StringWriter();
660         try (final Connection connection = getH2Connection()) {
661             setUpTable(connection);
662             try (final Statement stmt = connection.createStatement();
663                     final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT);
664                     final ResultSet resultSet = stmt.executeQuery("select ID, NAME, TEXT from TEST");) {
665                 printer.printRecords(resultSet);
666             }
667         }
668         assertEquals("1,r1,\"long text 1\"" + recordSeparator + "2,r2,\"" + longText2 + "\"" + recordSeparator, sw.toString());
669     }
670 
671     @Test
672     public void testJdbcPrinterWithResultSet() throws IOException, ClassNotFoundException, SQLException {
673         final StringWriter sw = new StringWriter();
674         Class.forName("org.h2.Driver");
675         try (final Connection connection = getH2Connection()) {
676             setUpTable(connection);
677             try (final Statement stmt = connection.createStatement();
678                     final ResultSet resultSet = stmt.executeQuery("select ID, NAME, TEXT from TEST");
679                     final CSVPrinter printer = CSVFormat.DEFAULT.withHeader(resultSet).print(sw)) {
680                 printer.printRecords(resultSet);
681             }
682         }
683         assertEquals("ID,NAME,TEXT" + recordSeparator + "1,r1,\"long text 1\"" + recordSeparator + "2,r2,\"" + longText2
684                 + "\"" + recordSeparator, sw.toString());
685     }
686 
687     @Test
688     public void testJdbcPrinterWithResultSetHeader() throws IOException, ClassNotFoundException, SQLException {
689         final StringWriter sw = new StringWriter();
690         try (final Connection connection = getH2Connection()) {
691             setUpTable(connection);
692             try (final Statement stmt = connection.createStatement();
693                 final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT);) {
694                 try (final ResultSet resultSet = stmt.executeQuery("select ID, NAME from TEST")) {
695                     printer.printRecords(resultSet, true);
696                     assertEquals("ID,NAME" + recordSeparator + "1,r1" + recordSeparator + "2,r2" + recordSeparator,
697                         sw.toString());
698                 }
699                 try (final ResultSet resultSet = stmt.executeQuery("select ID, NAME from TEST")) {
700                     printer.printRecords(resultSet, false);
701                     assertNotEquals("ID,NAME" + recordSeparator + "1,r1" + recordSeparator + "2,r2" + recordSeparator,
702                         sw.toString());
703                 }
704             }
705         }
706     }
707 
708     @Test
709     public void testJdbcPrinterWithResultSetMetaData() throws IOException, ClassNotFoundException, SQLException {
710         final StringWriter sw = new StringWriter();
711         Class.forName("org.h2.Driver");
712         try (final Connection connection = getH2Connection()) {
713             setUpTable(connection);
714             try (final Statement stmt = connection.createStatement();
715                     final ResultSet resultSet = stmt.executeQuery("select ID, NAME, TEXT from TEST");
716                     final CSVPrinter printer = CSVFormat.DEFAULT.withHeader(resultSet.getMetaData()).print(sw)) {
717                 printer.printRecords(resultSet);
718                 assertEquals("ID,NAME,TEXT" + recordSeparator + "1,r1,\"long text 1\"" + recordSeparator + "2,r2,\""
719                         + longText2 + "\"" + recordSeparator, sw.toString());
720             }
721         }
722     }
723 
724     @Test
725     @Disabled
726     public void testJira135_part1() throws IOException {
727         final CSVFormat format = CSVFormat.DEFAULT.withRecordSeparator('\n').withQuote(DQUOTE_CHAR).withEscape(BACKSLASH);
728         final StringWriter sw = new StringWriter();
729         final List<String> list = new LinkedList<>();
730         try (final CSVPrinter printer = new CSVPrinter(sw, format)) {
731             list.add("\"");
732             printer.printRecord(list);
733         }
734         final String expected = "\"\\\"\"" + format.getRecordSeparator();
735         assertEquals(expected, sw.toString());
736         final String[] record0 = toFirstRecordValues(expected, format);
737         assertArrayEquals(expectNulls(list.toArray(), format), record0);
738     }
739 
740     @Test
741     @Disabled
742     public void testJira135_part2() throws IOException {
743         final CSVFormat format = CSVFormat.DEFAULT.withRecordSeparator('\n').withQuote(DQUOTE_CHAR).withEscape(BACKSLASH);
744         final StringWriter sw = new StringWriter();
745         final List<String> list = new LinkedList<>();
746         try (final CSVPrinter printer = new CSVPrinter(sw, format)) {
747             list.add("\n");
748             printer.printRecord(list);
749         }
750         final String expected = "\"\\n\"" + format.getRecordSeparator();
751         assertEquals(expected, sw.toString());
752         final String[] record0 = toFirstRecordValues(expected, format);
753         assertArrayEquals(expectNulls(list.toArray(), format), record0);
754     }
755 
756     @Test
757     @Disabled
758     public void testJira135_part3() throws IOException {
759         final CSVFormat format = CSVFormat.DEFAULT.withRecordSeparator('\n').withQuote(DQUOTE_CHAR).withEscape(BACKSLASH);
760         final StringWriter sw = new StringWriter();
761         final List<String> list = new LinkedList<>();
762         try (final CSVPrinter printer = new CSVPrinter(sw, format)) {
763             list.add("\\");
764             printer.printRecord(list);
765         }
766         final String expected = "\"\\\\\"" + format.getRecordSeparator();
767         assertEquals(expected, sw.toString());
768         final String[] record0 = toFirstRecordValues(expected, format);
769         assertArrayEquals(expectNulls(list.toArray(), format), record0);
770     }
771 
772     @Test
773     @Disabled
774     public void testJira135All() throws IOException {
775         final CSVFormat format = CSVFormat.DEFAULT.withRecordSeparator('\n').withQuote(DQUOTE_CHAR).withEscape(BACKSLASH);
776         final StringWriter sw = new StringWriter();
777         final List<String> list = new LinkedList<>();
778         try (final CSVPrinter printer = new CSVPrinter(sw, format)) {
779             list.add("\"");
780             list.add("\n");
781             list.add("\\");
782             printer.printRecord(list);
783         }
784         final String expected = "\"\\\"\",\"\\n\",\"\\\"" + format.getRecordSeparator();
785         assertEquals(expected, sw.toString());
786         final String[] record0 = toFirstRecordValues(expected, format);
787         assertArrayEquals(expectNulls(list.toArray(), format), record0);
788     }
789 
790     @Test
791     public void testMongoDbCsvBasic() throws IOException {
792         final StringWriter sw = new StringWriter();
793         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.MONGODB_CSV)) {
794             printer.printRecord("a", "b");
795             assertEquals("a,b" + recordSeparator, sw.toString());
796         }
797     }
798 
799     @Test
800     public void testMongoDbCsvCommaInValue() throws IOException {
801         final StringWriter sw = new StringWriter();
802         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.MONGODB_CSV)) {
803             printer.printRecord("a,b", "c");
804             assertEquals("\"a,b\",c" + recordSeparator, sw.toString());
805         }
806     }
807 
808     @Test
809     public void testMongoDbCsvDoubleQuoteInValue() throws IOException {
810         final StringWriter sw = new StringWriter();
811         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.MONGODB_CSV)) {
812             printer.printRecord("a \"c\" b", "d");
813             assertEquals("\"a \"\"c\"\" b\",d" + recordSeparator, sw.toString());
814         }
815     }
816 
817     @Test
818     public void testMongoDbCsvTabInValue() throws IOException {
819         final StringWriter sw = new StringWriter();
820         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.MONGODB_CSV)) {
821             printer.printRecord("a\tb", "c");
822             assertEquals("a\tb,c" + recordSeparator, sw.toString());
823         }
824     }
825 
826     @Test
827     public void testMongoDbTsvBasic() throws IOException {
828         final StringWriter sw = new StringWriter();
829         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.MONGODB_TSV)) {
830             printer.printRecord("a", "b");
831             assertEquals("a\tb" + recordSeparator, sw.toString());
832         }
833     }
834 
835     @Test
836     public void testMongoDbTsvCommaInValue() throws IOException {
837         final StringWriter sw = new StringWriter();
838         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.MONGODB_TSV)) {
839             printer.printRecord("a,b", "c");
840             assertEquals("a,b\tc" + recordSeparator, sw.toString());
841         }
842     }
843 
844     @Test
845     public void testMongoDbTsvTabInValue() throws IOException {
846         final StringWriter sw = new StringWriter();
847         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.MONGODB_TSV)) {
848             printer.printRecord("a\tb", "c");
849             assertEquals("\"a\tb\"\tc" + recordSeparator, sw.toString());
850         }
851     }
852 
853     @Test
854     public void testMultiLineComment() throws IOException {
855         final StringWriter sw = new StringWriter();
856         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withCommentMarker('#'))) {
857             printer.printComment("This is a comment\non multiple lines");
858 
859             assertEquals("# This is a comment" + recordSeparator + "# on multiple lines" + recordSeparator,
860                     sw.toString());
861         }
862     }
863 
864     @Test
865     public void testMySqlNullOutput() throws IOException {
866         Object[] s = new String[] { "NULL", null };
867         CSVFormat format = CSVFormat.MYSQL.withQuote(DQUOTE_CHAR).withNullString("NULL")
868             .withQuoteMode(QuoteMode.NON_NUMERIC);
869         StringWriter writer = new StringWriter();
870         try (final CSVPrinter printer = new CSVPrinter(writer, format)) {
871             printer.printRecord(s);
872         }
873         String expected = "\"NULL\"\tNULL\n";
874         assertEquals(expected, writer.toString());
875         String[] record0 = toFirstRecordValues(expected, format);
876         assertArrayEquals(s, record0);
877 
878         s = new String[] { "\\N", null };
879         format = CSVFormat.MYSQL.withNullString("\\N");
880         writer = new StringWriter();
881         try (final CSVPrinter printer = new CSVPrinter(writer, format)) {
882             printer.printRecord(s);
883         }
884         expected = "\\\\N\t\\N\n";
885         assertEquals(expected, writer.toString());
886         record0 = toFirstRecordValues(expected, format);
887         assertArrayEquals(expectNulls(s, format), record0);
888 
889         s = new String[] { "\\N", "A" };
890         format = CSVFormat.MYSQL.withNullString("\\N");
891         writer = new StringWriter();
892         try (final CSVPrinter printer = new CSVPrinter(writer, format)) {
893             printer.printRecord(s);
894         }
895         expected = "\\\\N\tA\n";
896         assertEquals(expected, writer.toString());
897         record0 = toFirstRecordValues(expected, format);
898         assertArrayEquals(expectNulls(s, format), record0);
899 
900         s = new String[] { "\n", "A" };
901         format = CSVFormat.MYSQL.withNullString("\\N");
902         writer = new StringWriter();
903         try (final CSVPrinter printer = new CSVPrinter(writer, format)) {
904             printer.printRecord(s);
905         }
906         expected = "\\n\tA\n";
907         assertEquals(expected, writer.toString());
908         record0 = toFirstRecordValues(expected, format);
909         assertArrayEquals(expectNulls(s, format), record0);
910 
911         s = new String[] { "", null };
912         format = CSVFormat.MYSQL.withNullString("NULL");
913         writer = new StringWriter();
914         try (final CSVPrinter printer = new CSVPrinter(writer, format)) {
915             printer.printRecord(s);
916         }
917         expected = "\tNULL\n";
918         assertEquals(expected, writer.toString());
919         record0 = toFirstRecordValues(expected, format);
920         assertArrayEquals(expectNulls(s, format), record0);
921 
922         s = new String[] { "", null };
923         format = CSVFormat.MYSQL;
924         writer = new StringWriter();
925         try (final CSVPrinter printer = new CSVPrinter(writer, format)) {
926             printer.printRecord(s);
927         }
928         expected = "\t\\N\n";
929         assertEquals(expected, writer.toString());
930         record0 = toFirstRecordValues(expected, format);
931         assertArrayEquals(expectNulls(s, format), record0);
932 
933         s = new String[] { "\\N", "", "\u000e,\\\r" };
934         format = CSVFormat.MYSQL;
935         writer = new StringWriter();
936         try (final CSVPrinter printer = new CSVPrinter(writer, format)) {
937             printer.printRecord(s);
938         }
939         expected = "\\\\N\t\t\u000e,\\\\\\r\n";
940         assertEquals(expected, writer.toString());
941         record0 = toFirstRecordValues(expected, format);
942         assertArrayEquals(expectNulls(s, format), record0);
943 
944         s = new String[] { "NULL", "\\\r" };
945         format = CSVFormat.MYSQL;
946         writer = new StringWriter();
947         try (final CSVPrinter printer = new CSVPrinter(writer, format)) {
948             printer.printRecord(s);
949         }
950         expected = "NULL\t\\\\\\r\n";
951         assertEquals(expected, writer.toString());
952         record0 = toFirstRecordValues(expected, format);
953         assertArrayEquals(expectNulls(s, format), record0);
954 
955         s = new String[] { "\\\r" };
956         format = CSVFormat.MYSQL;
957         writer = new StringWriter();
958         try (final CSVPrinter printer = new CSVPrinter(writer, format)) {
959             printer.printRecord(s);
960         }
961         expected = "\\\\\\r\n";
962         assertEquals(expected, writer.toString());
963         record0 = toFirstRecordValues(expected, format);
964         assertArrayEquals(expectNulls(s, format), record0);
965     }
966 
967     @Test
968     public void testMySqlNullStringDefault() {
969         assertEquals("\\N", CSVFormat.MYSQL.getNullString());
970     }
971 
972     @Test
973     public void testNewCsvPrinterAppendableNullFormat() {
974         assertThrows(NullPointerException.class, () -> new CSVPrinter(new StringWriter(), null));
975     }
976 
977     @Test
978     public void testNewCsvPrinterNullAppendableFormat() {
979         assertThrows(NullPointerException.class, () -> new CSVPrinter(null, CSVFormat.DEFAULT));
980     }
981 
982     @Test
983     public void testNotFlushable() throws IOException {
984         final Appendable out = new StringBuilder();
985         try (final CSVPrinter printer = new CSVPrinter(out, CSVFormat.DEFAULT)) {
986             printer.printRecord("a", "b", "c");
987             assertEquals("a,b,c" + recordSeparator, out.toString());
988             printer.flush();
989         }
990     }
991 
992     @Test
993     public void testParseCustomNullValues() throws IOException {
994         final StringWriter sw = new StringWriter();
995         final CSVFormat format = CSVFormat.DEFAULT.withNullString("NULL");
996         try (final CSVPrinter printer = new CSVPrinter(sw, format)) {
997             printer.printRecord("a", null, "b");
998         }
999         final String csvString = sw.toString();
1000         assertEquals("a,NULL,b" + recordSeparator, csvString);
1001         try (final CSVParser iterable = format.parse(new StringReader(csvString))) {
1002             final Iterator<CSVRecord> iterator = iterable.iterator();
1003             final CSVRecord record = iterator.next();
1004             assertEquals("a", record.get(0));
1005             assertNull(record.get(1));
1006             assertEquals("b", record.get(2));
1007             assertFalse(iterator.hasNext());
1008         }
1009     }
1010 
1011     @Test
1012     public void testPlainEscaped() throws IOException {
1013         final StringWriter sw = new StringWriter();
1014         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(null).withEscape('!'))) {
1015             printer.print("abc");
1016             printer.print("xyz");
1017             assertEquals("abc,xyz", sw.toString());
1018         }
1019     }
1020 
1021     @Test
1022     public void testPlainPlain() throws IOException {
1023         final StringWriter sw = new StringWriter();
1024         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(null))) {
1025             printer.print("abc");
1026             printer.print("xyz");
1027             assertEquals("abc,xyz", sw.toString());
1028         }
1029     }
1030 
1031     @Test
1032     public void testPlainQuoted() throws IOException {
1033         final StringWriter sw = new StringWriter();
1034         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote('\''))) {
1035             printer.print("abc");
1036             assertEquals("abc", sw.toString());
1037         }
1038     }
1039 
1040     @Test
1041     @Disabled
1042     public void testPostgreSqlCsvNullOutput() throws IOException {
1043         Object[] s = new String[] { "NULL", null };
1044         CSVFormat format = CSVFormat.POSTGRESQL_CSV.withQuote(DQUOTE_CHAR).withNullString("NULL").withQuoteMode(QuoteMode.ALL_NON_NULL);
1045         StringWriter writer = new StringWriter();
1046         try (final CSVPrinter printer = new CSVPrinter(writer, format)) {
1047             printer.printRecord(s);
1048         }
1049         String expected = "\"NULL\",NULL\n";
1050         assertEquals(expected, writer.toString());
1051         String[] record0 = toFirstRecordValues(expected, format);
1052         assertArrayEquals(new Object[2], record0);
1053 
1054         s = new String[] { "\\N", null };
1055         format = CSVFormat.POSTGRESQL_CSV.withNullString("\\N");
1056         writer = new StringWriter();
1057         try (final CSVPrinter printer = new CSVPrinter(writer, format)) {
1058             printer.printRecord(s);
1059         }
1060         expected = "\\\\N\t\\N\n";
1061         assertEquals(expected, writer.toString());
1062         record0 = toFirstRecordValues(expected, format);
1063         assertArrayEquals(expectNulls(s, format), record0);
1064 
1065         s = new String[] { "\\N", "A" };
1066         format = CSVFormat.POSTGRESQL_CSV.withNullString("\\N");
1067         writer = new StringWriter();
1068         try (final CSVPrinter printer = new CSVPrinter(writer, format)) {
1069             printer.printRecord(s);
1070         }
1071         expected = "\\\\N\tA\n";
1072         assertEquals(expected, writer.toString());
1073         record0 = toFirstRecordValues(expected, format);
1074         assertArrayEquals(expectNulls(s, format), record0);
1075 
1076         s = new String[] { "\n", "A" };
1077         format = CSVFormat.POSTGRESQL_CSV.withNullString("\\N");
1078         writer = new StringWriter();
1079         try (final CSVPrinter printer = new CSVPrinter(writer, format)) {
1080             printer.printRecord(s);
1081         }
1082         expected = "\\n\tA\n";
1083         assertEquals(expected, writer.toString());
1084         record0 = toFirstRecordValues(expected, format);
1085         assertArrayEquals(expectNulls(s, format), record0);
1086 
1087         s = new String[] { "", null };
1088         format = CSVFormat.POSTGRESQL_CSV.withNullString("NULL");
1089         writer = new StringWriter();
1090         try (final CSVPrinter printer = new CSVPrinter(writer, format)) {
1091             printer.printRecord(s);
1092         }
1093         expected = "\tNULL\n";
1094         assertEquals(expected, writer.toString());
1095         record0 = toFirstRecordValues(expected, format);
1096         assertArrayEquals(expectNulls(s, format), record0);
1097 
1098         s = new String[] { "", null };
1099         format = CSVFormat.POSTGRESQL_CSV;
1100         writer = new StringWriter();
1101         try (final CSVPrinter printer = new CSVPrinter(writer, format)) {
1102             printer.printRecord(s);
1103         }
1104         expected = "\t\\N\n";
1105         assertEquals(expected, writer.toString());
1106         record0 = toFirstRecordValues(expected, format);
1107         assertArrayEquals(expectNulls(s, format), record0);
1108 
1109         s = new String[] { "\\N", "", "\u000e,\\\r" };
1110         format = CSVFormat.POSTGRESQL_CSV;
1111         writer = new StringWriter();
1112         try (final CSVPrinter printer = new CSVPrinter(writer, format)) {
1113             printer.printRecord(s);
1114         }
1115         expected = "\\\\N\t\t\u000e,\\\\\\r\n";
1116         assertEquals(expected, writer.toString());
1117         record0 = toFirstRecordValues(expected, format);
1118         assertArrayEquals(expectNulls(s, format), record0);
1119 
1120         s = new String[] { "NULL", "\\\r" };
1121         format = CSVFormat.POSTGRESQL_CSV;
1122         writer = new StringWriter();
1123         try (final CSVPrinter printer = new CSVPrinter(writer, format)) {
1124             printer.printRecord(s);
1125         }
1126         expected = "NULL\t\\\\\\r\n";
1127         assertEquals(expected, writer.toString());
1128         record0 = toFirstRecordValues(expected, format);
1129         assertArrayEquals(expectNulls(s, format), record0);
1130 
1131         s = new String[] { "\\\r" };
1132         format = CSVFormat.POSTGRESQL_CSV;
1133         writer = new StringWriter();
1134         try (final CSVPrinter printer = new CSVPrinter(writer, format)) {
1135             printer.printRecord(s);
1136         }
1137         expected = "\\\\\\r\n";
1138         assertEquals(expected, writer.toString());
1139         record0 = toFirstRecordValues(expected, format);
1140         assertArrayEquals(expectNulls(s, format), record0);
1141     }
1142 
1143     @Test
1144     @Disabled
1145     public void testPostgreSqlCsvTextOutput() throws IOException {
1146         Object[] s = new String[] { "NULL", null };
1147         CSVFormat format = CSVFormat.POSTGRESQL_TEXT.withQuote(DQUOTE_CHAR).withNullString("NULL").withQuoteMode(QuoteMode.ALL_NON_NULL);
1148         StringWriter writer = new StringWriter();
1149         try (final CSVPrinter printer = new CSVPrinter(writer, format)) {
1150             printer.printRecord(s);
1151         }
1152         String expected = "\"NULL\"\tNULL\n";
1153         assertEquals(expected, writer.toString());
1154         String[] record0 = toFirstRecordValues(expected, format);
1155         assertArrayEquals(new Object[2], record0);
1156 
1157         s = new String[] { "\\N", null };
1158         format = CSVFormat.POSTGRESQL_TEXT.withNullString("\\N");
1159         writer = new StringWriter();
1160         try (final CSVPrinter printer = new CSVPrinter(writer, format)) {
1161             printer.printRecord(s);
1162         }
1163         expected = "\\\\N\t\\N\n";
1164         assertEquals(expected, writer.toString());
1165         record0 = toFirstRecordValues(expected, format);
1166         assertArrayEquals(expectNulls(s, format), record0);
1167 
1168         s = new String[] { "\\N", "A" };
1169         format = CSVFormat.POSTGRESQL_TEXT.withNullString("\\N");
1170         writer = new StringWriter();
1171         try (final CSVPrinter printer = new CSVPrinter(writer, format)) {
1172             printer.printRecord(s);
1173         }
1174         expected = "\\\\N\tA\n";
1175         assertEquals(expected, writer.toString());
1176         record0 = toFirstRecordValues(expected, format);
1177         assertArrayEquals(expectNulls(s, format), record0);
1178 
1179         s = new String[] { "\n", "A" };
1180         format = CSVFormat.POSTGRESQL_TEXT.withNullString("\\N");
1181         writer = new StringWriter();
1182         try (final CSVPrinter printer = new CSVPrinter(writer, format)) {
1183             printer.printRecord(s);
1184         }
1185         expected = "\\n\tA\n";
1186         assertEquals(expected, writer.toString());
1187         record0 = toFirstRecordValues(expected, format);
1188         assertArrayEquals(expectNulls(s, format), record0);
1189 
1190         s = new String[] { "", null };
1191         format = CSVFormat.POSTGRESQL_TEXT.withNullString("NULL");
1192         writer = new StringWriter();
1193         try (final CSVPrinter printer = new CSVPrinter(writer, format)) {
1194             printer.printRecord(s);
1195         }
1196         expected = "\tNULL\n";
1197         assertEquals(expected, writer.toString());
1198         record0 = toFirstRecordValues(expected, format);
1199         assertArrayEquals(expectNulls(s, format), record0);
1200 
1201         s = new String[] { "", null };
1202         format = CSVFormat.POSTGRESQL_TEXT;
1203         writer = new StringWriter();
1204         try (final CSVPrinter printer = new CSVPrinter(writer, format)) {
1205             printer.printRecord(s);
1206         }
1207         expected = "\t\\N\n";
1208         assertEquals(expected, writer.toString());
1209         record0 = toFirstRecordValues(expected, format);
1210         assertArrayEquals(expectNulls(s, format), record0);
1211 
1212         s = new String[] { "\\N", "", "\u000e,\\\r" };
1213         format = CSVFormat.POSTGRESQL_TEXT;
1214         writer = new StringWriter();
1215         try (final CSVPrinter printer = new CSVPrinter(writer, format)) {
1216             printer.printRecord(s);
1217         }
1218         expected = "\\\\N\t\t\u000e,\\\\\\r\n";
1219         assertEquals(expected, writer.toString());
1220         record0 = toFirstRecordValues(expected, format);
1221         assertArrayEquals(expectNulls(s, format), record0);
1222 
1223         s = new String[] { "NULL", "\\\r" };
1224         format = CSVFormat.POSTGRESQL_TEXT;
1225         writer = new StringWriter();
1226         try (final CSVPrinter printer = new CSVPrinter(writer, format)) {
1227             printer.printRecord(s);
1228         }
1229         expected = "NULL\t\\\\\\r\n";
1230         assertEquals(expected, writer.toString());
1231         record0 = toFirstRecordValues(expected, format);
1232         assertArrayEquals(expectNulls(s, format), record0);
1233 
1234         s = new String[] { "\\\r" };
1235         format = CSVFormat.POSTGRESQL_TEXT;
1236         writer = new StringWriter();
1237         try (final CSVPrinter printer = new CSVPrinter(writer, format)) {
1238             printer.printRecord(s);
1239         }
1240         expected = "\\\\\\r\n";
1241         assertEquals(expected, writer.toString());
1242         record0 = toFirstRecordValues(expected, format);
1243         assertArrayEquals(expectNulls(s, format), record0);
1244     }
1245 
1246     @Test
1247     public void testPostgreSqlNullStringDefaultCsv() {
1248         assertEquals("", CSVFormat.POSTGRESQL_CSV.getNullString());
1249     }
1250 
1251     @Test
1252     public void testPostgreSqlNullStringDefaultText() {
1253         assertEquals("\\N", CSVFormat.POSTGRESQL_TEXT.getNullString());
1254     }
1255 
1256     @Test
1257     public void testPrint() throws IOException {
1258         final StringWriter sw = new StringWriter();
1259         try (final CSVPrinter printer = CSVFormat.DEFAULT.print(sw)) {
1260             printer.printRecord("a", "b\\c");
1261             assertEquals("a,b\\c" + recordSeparator, sw.toString());
1262         }
1263     }
1264 
1265     @Test
1266     public void testPrintCSVParser() throws IOException {
1267         final String code = "a1,b1\n" // 1)
1268             + "a2,b2\n" // 2)
1269             + "a3,b3\n" // 3)
1270             + "a4,b4\n"// 4)
1271         ;
1272         final String[][] res = {{"a1", "b1"}, {"a2", "b2"}, {"a3", "b3"}, {"a4", "b4"}};
1273         final CSVFormat format = CSVFormat.DEFAULT;
1274         final StringWriter sw = new StringWriter();
1275         try (final CSVPrinter printer = format.print(sw); final CSVParser parser = CSVParser.parse(code, format)) {
1276             printer.printRecords(parser);
1277         }
1278         try (final CSVParser parser = CSVParser.parse(sw.toString(), format)) {
1279             final List<CSVRecord> records = parser.getRecords();
1280             assertFalse(records.isEmpty());
1281             Utils.compare("Fail", res, records);
1282         }
1283     }
1284 
1285     @Test
1286     public void testPrintCSVRecord() throws IOException {
1287         final String code = "a1,b1\n" // 1)
1288             + "a2,b2\n" // 2)
1289             + "a3,b3\n" // 3)
1290             + "a4,b4\n"// 4)
1291         ;
1292         final String[][] res = {{"a1", "b1"}, {"a2", "b2"}, {"a3", "b3"}, {"a4", "b4"}};
1293         final CSVFormat format = CSVFormat.DEFAULT;
1294         final StringWriter sw = new StringWriter();
1295         try (final CSVPrinter printer = format.print(sw); final CSVParser parser = CSVParser.parse(code, format)) {
1296             for (final CSVRecord record : parser) {
1297                 printer.printRecord(record);
1298             }
1299         }
1300         try (final CSVParser parser = CSVParser.parse(sw.toString(), format)) {
1301             final List<CSVRecord> records = parser.getRecords();
1302             assertFalse(records.isEmpty());
1303             Utils.compare("Fail", res, records);
1304         }
1305     }
1306 
1307     @Test
1308     public void testPrintCSVRecords() throws IOException {
1309         final String code = "a1,b1\n" // 1)
1310             + "a2,b2\n" // 2)
1311             + "a3,b3\n" // 3)
1312             + "a4,b4\n"// 4)
1313         ;
1314         final String[][] res = {{"a1", "b1"}, {"a2", "b2"}, {"a3", "b3"}, {"a4", "b4"}};
1315         final CSVFormat format = CSVFormat.DEFAULT;
1316         final StringWriter sw = new StringWriter();
1317         try (final CSVPrinter printer = format.print(sw); final CSVParser parser = CSVParser.parse(code, format)) {
1318             printer.printRecords(parser.getRecords());
1319         }
1320         try (final CSVParser parser = CSVParser.parse(sw.toString(), format)) {
1321             final List<CSVRecord> records = parser.getRecords();
1322             assertFalse(records.isEmpty());
1323             Utils.compare("Fail", res, records);
1324         }
1325     }
1326 
1327     @Test
1328     public void testPrintCustomNullValues() throws IOException {
1329         final StringWriter sw = new StringWriter();
1330         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withNullString("NULL"))) {
1331             printer.printRecord("a", null, "b");
1332             assertEquals("a,NULL,b" + recordSeparator, sw.toString());
1333         }
1334     }
1335 
1336     @Test
1337     public void testPrinter1() throws IOException {
1338         final StringWriter sw = new StringWriter();
1339         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT)) {
1340             printer.printRecord("a", "b");
1341             assertEquals("a,b" + recordSeparator, sw.toString());
1342         }
1343     }
1344 
1345     @Test
1346     public void testPrinter2() throws IOException {
1347         final StringWriter sw = new StringWriter();
1348         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT)) {
1349             printer.printRecord("a,b", "b");
1350             assertEquals("\"a,b\",b" + recordSeparator, sw.toString());
1351         }
1352     }
1353 
1354     @Test
1355     public void testPrinter3() throws IOException {
1356         final StringWriter sw = new StringWriter();
1357         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT)) {
1358             printer.printRecord("a, b", "b ");
1359             assertEquals("\"a, b\",\"b \"" + recordSeparator, sw.toString());
1360         }
1361     }
1362 
1363     @Test
1364     public void testPrinter4() throws IOException {
1365         final StringWriter sw = new StringWriter();
1366         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT)) {
1367             printer.printRecord("a", "b\"c");
1368             assertEquals("a,\"b\"\"c\"" + recordSeparator, sw.toString());
1369         }
1370     }
1371 
1372     @Test
1373     public void testPrinter5() throws IOException {
1374         final StringWriter sw = new StringWriter();
1375         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT)) {
1376             printer.printRecord("a", "b\nc");
1377             assertEquals("a,\"b\nc\"" + recordSeparator, sw.toString());
1378         }
1379     }
1380 
1381     @Test
1382     public void testPrinter6() throws IOException {
1383         final StringWriter sw = new StringWriter();
1384         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT)) {
1385             printer.printRecord("a", "b\r\nc");
1386             assertEquals("a,\"b\r\nc\"" + recordSeparator, sw.toString());
1387         }
1388     }
1389 
1390     @Test
1391     public void testPrinter7() throws IOException {
1392         final StringWriter sw = new StringWriter();
1393         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT)) {
1394             printer.printRecord("a", "b\\c");
1395             assertEquals("a,b\\c" + recordSeparator, sw.toString());
1396         }
1397     }
1398 
1399     @Test
1400     public void testPrintNullValues() throws IOException {
1401         final StringWriter sw = new StringWriter();
1402         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT)) {
1403             printer.printRecord("a", null, "b");
1404             assertEquals("a,,b" + recordSeparator, sw.toString());
1405         }
1406     }
1407 
1408     @Test
1409     public void testPrintOnePositiveInteger() throws IOException {
1410         final StringWriter sw = new StringWriter();
1411         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuoteMode(QuoteMode.MINIMAL))) {
1412             printer.print(Integer.MAX_VALUE);
1413             assertEquals(String.valueOf(Integer.MAX_VALUE), sw.toString());
1414         }
1415     }
1416 
1417     /**
1418      * Test to target the use of {@link IOUtils#copy(java.io.Reader, Appendable)} which directly
1419      * buffers the value from the Reader to the Appendable.
1420      *
1421      * <p>Requires the format to have no quote or escape character, value to be a
1422      * {@link java.io.Reader Reader} and the output <i>MUST NOT</i> be a
1423      * {@link java.io.Writer Writer} but some other Appendable.</p>
1424      *
1425      * @throws IOException Not expected to happen
1426      */
1427     @Test
1428     public void testPrintReaderWithoutQuoteToAppendable() throws IOException {
1429         final StringBuilder sb = new StringBuilder();
1430         final String content = "testValue";
1431         try (final CSVPrinter printer = new CSVPrinter(sb, CSVFormat.DEFAULT.withQuote(null))) {
1432             final StringReader value = new StringReader(content);
1433             printer.print(value);
1434         }
1435         assertEquals(content, sb.toString());
1436     }
1437 
1438     /**
1439      * Test to target the use of {@link IOUtils#copyLarge(java.io.Reader, Writer)} which directly
1440      * buffers the value from the Reader to the Writer.
1441      *
1442      * <p>Requires the format to have no quote or escape character, value to be a
1443      * {@link java.io.Reader Reader} and the output <i>MUST</i> be a
1444      * {@link java.io.Writer Writer}.</p>
1445      *
1446      * @throws IOException Not expected to happen
1447      */
1448     @Test
1449     public void testPrintReaderWithoutQuoteToWriter() throws IOException {
1450         final StringWriter sw = new StringWriter();
1451         final String content = "testValue";
1452         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(null))) {
1453             final StringReader value = new StringReader(content);
1454             printer.print(value);
1455         }
1456         assertEquals(content, sw.toString());
1457     }
1458 
1459     @Test
1460     public void testPrintRecordsWithCSVRecord() throws IOException {
1461         final String[] values = {"A", "B", "C"};
1462         final String rowData = StringUtils.join(values, ',');
1463         final CharArrayWriter charArrayWriter = new CharArrayWriter(0);
1464         try (final CSVParser parser = CSVFormat.DEFAULT.parse(new StringReader(rowData));
1465             final CSVPrinter csvPrinter = CSVFormat.INFORMIX_UNLOAD.print(charArrayWriter)) {
1466             for (final CSVRecord record : parser) {
1467                 csvPrinter.printRecord(record);
1468             }
1469         }
1470         assertEquals(6, charArrayWriter.size());
1471         assertEquals("A|B|C" + CSVFormat.INFORMIX_UNLOAD.getRecordSeparator(), charArrayWriter.toString());
1472     }
1473 
1474     @Test
1475     public void testPrintRecordsWithEmptyVector() throws IOException {
1476         final PrintStream out = System.out;
1477         try {
1478             System.setOut(new PrintStream(NullOutputStream.NULL_OUTPUT_STREAM));
1479             try (CSVPrinter csvPrinter = CSVFormat.POSTGRESQL_TEXT.printer()) {
1480                 final Vector<CSVFormatTest.EmptyEnum> vector = new Vector<>();
1481                 final int expectedCapacity = 23;
1482                 vector.setSize(expectedCapacity);
1483                 csvPrinter.printRecords(vector);
1484                 assertEquals(expectedCapacity, vector.capacity());
1485             }
1486         } finally {
1487             System.setOut(out);
1488         }
1489     }
1490 
1491     @Test
1492     public void testPrintRecordsWithObjectArray() throws IOException {
1493         final CharArrayWriter charArrayWriter = new CharArrayWriter(0);
1494         try (CSVPrinter csvPrinter = CSVFormat.INFORMIX_UNLOAD.print(charArrayWriter)) {
1495             final HashSet<BatchUpdateException> hashSet = new HashSet<>();
1496             final Object[] objectArray = new Object[6];
1497             objectArray[3] = hashSet;
1498             csvPrinter.printRecords(objectArray);
1499         }
1500         assertEquals(6, charArrayWriter.size());
1501         assertEquals("\n\n\n\n\n\n", charArrayWriter.toString());
1502     }
1503 
1504     @Test
1505     public void testPrintRecordsWithResultSetOneRow() throws IOException, SQLException {
1506         try (CSVPrinter csvPrinter = CSVFormat.MYSQL.printer()) {
1507             try (ResultSet resultSet = new SimpleResultSet()) {
1508                 csvPrinter.printRecords(resultSet);
1509                 assertEquals(0, resultSet.getRow());
1510             }
1511         }
1512     }
1513 
1514     @Test
1515     public void testPrintToFileWithCharsetUtf16Be() throws IOException {
1516         final File file = File.createTempFile(getClass().getName(), ".csv");
1517         try (final CSVPrinter printer = CSVFormat.DEFAULT.print(file, StandardCharsets.UTF_16BE)) {
1518             printer.printRecord("a", "b\\c");
1519         }
1520         assertEquals("a,b\\c" + recordSeparator, FileUtils.readFileToString(file, StandardCharsets.UTF_16BE));
1521     }
1522 
1523     @Test
1524     public void testPrintToFileWithDefaultCharset() throws IOException {
1525         final File file = File.createTempFile(getClass().getName(), ".csv");
1526         try (final CSVPrinter printer = CSVFormat.DEFAULT.print(file, Charset.defaultCharset())) {
1527             printer.printRecord("a", "b\\c");
1528         }
1529         assertEquals("a,b\\c" + recordSeparator, FileUtils.readFileToString(file, Charset.defaultCharset()));
1530     }
1531 
1532     @Test
1533     public void testPrintToPathWithDefaultCharset() throws IOException {
1534         final File file = File.createTempFile(getClass().getName(), ".csv");
1535         try (final CSVPrinter printer = CSVFormat.DEFAULT.print(file.toPath(), Charset.defaultCharset())) {
1536             printer.printRecord("a", "b\\c");
1537         }
1538         assertEquals("a,b\\c" + recordSeparator, FileUtils.readFileToString(file, Charset.defaultCharset()));
1539     }
1540 
1541     @Test
1542     public void testQuoteAll() throws IOException {
1543         final StringWriter sw = new StringWriter();
1544         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuoteMode(QuoteMode.ALL))) {
1545             printer.printRecord("a", "b\nc", "d");
1546             assertEquals("\"a\",\"b\nc\",\"d\"" + recordSeparator, sw.toString());
1547         }
1548     }
1549 
1550     @Test
1551     public void testQuoteCommaFirstChar() throws IOException {
1552         final StringWriter sw = new StringWriter();
1553         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.RFC4180)) {
1554             printer.printRecord(",");
1555             assertEquals("\",\"" + recordSeparator, sw.toString());
1556         }
1557     }
1558 
1559     @Test
1560     public void testQuoteNonNumeric() throws IOException {
1561         final StringWriter sw = new StringWriter();
1562         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuoteMode(QuoteMode.NON_NUMERIC))) {
1563             printer.printRecord("a", "b\nc", Integer.valueOf(1));
1564             assertEquals("\"a\",\"b\nc\",1" + recordSeparator, sw.toString());
1565         }
1566     }
1567 
1568     @Test
1569     public void testRandomDefault() throws Exception {
1570         doRandom(CSVFormat.DEFAULT, ITERATIONS_FOR_RANDOM_TEST);
1571     }
1572 
1573     @Test
1574     public void testRandomExcel() throws Exception {
1575         doRandom(CSVFormat.EXCEL, ITERATIONS_FOR_RANDOM_TEST);
1576     }
1577 
1578     @Test
1579     @Disabled
1580     public void testRandomMongoDbCsv() throws Exception {
1581         doRandom(CSVFormat.MONGODB_CSV, ITERATIONS_FOR_RANDOM_TEST);
1582     }
1583 
1584     @Test
1585     public void testRandomMySql() throws Exception {
1586         doRandom(CSVFormat.MYSQL, ITERATIONS_FOR_RANDOM_TEST);
1587     }
1588 
1589     @Test
1590     @Disabled
1591     public void testRandomOracle() throws Exception {
1592         doRandom(CSVFormat.ORACLE, ITERATIONS_FOR_RANDOM_TEST);
1593     }
1594 
1595     @Test
1596     @Disabled
1597     public void testRandomPostgreSqlCsv() throws Exception {
1598         doRandom(CSVFormat.POSTGRESQL_CSV, ITERATIONS_FOR_RANDOM_TEST);
1599     }
1600 
1601     @Test
1602     @Disabled
1603     public void testRandomPostgreSqlText() throws Exception {
1604         doRandom(CSVFormat.POSTGRESQL_TEXT, ITERATIONS_FOR_RANDOM_TEST);
1605     }
1606 
1607 
1608     @Test
1609     public void testRandomRfc4180() throws Exception {
1610         doRandom(CSVFormat.RFC4180, ITERATIONS_FOR_RANDOM_TEST);
1611     }
1612 
1613     @Test
1614     public void testRandomTdf() throws Exception {
1615         doRandom(CSVFormat.TDF, ITERATIONS_FOR_RANDOM_TEST);
1616     }
1617 
1618     @Test
1619     public void testSingleLineComment() throws IOException {
1620         final StringWriter sw = new StringWriter();
1621         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withCommentMarker('#'))) {
1622             printer.printComment("This is a comment");
1623             assertEquals("# This is a comment" + recordSeparator, sw.toString());
1624         }
1625     }
1626 
1627     @Test
1628     public void testSingleQuoteQuoted() throws IOException {
1629         final StringWriter sw = new StringWriter();
1630         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote('\''))) {
1631             printer.print("a'b'c");
1632             printer.print("xyz");
1633             assertEquals("'a''b''c',xyz", sw.toString());
1634         }
1635     }
1636 
1637     @Test
1638     public void testSkipHeaderRecordFalse() throws IOException {
1639         // functionally identical to testHeader, used to test CSV-153
1640         final StringWriter sw = new StringWriter();
1641         try (final CSVPrinter printer = new CSVPrinter(sw,
1642                 CSVFormat.DEFAULT.withQuote(null).withHeader("C1", "C2", "C3").withSkipHeaderRecord(false))) {
1643             printer.printRecord("a", "b", "c");
1644             printer.printRecord("x", "y", "z");
1645             assertEquals("C1,C2,C3\r\na,b,c\r\nx,y,z\r\n", sw.toString());
1646         }
1647     }
1648 
1649     @Test
1650     public void testSkipHeaderRecordTrue() throws IOException {
1651         // functionally identical to testHeaderNotSet, used to test CSV-153
1652         final StringWriter sw = new StringWriter();
1653         try (final CSVPrinter printer = new CSVPrinter(sw,
1654                 CSVFormat.DEFAULT.withQuote(null).withHeader("C1", "C2", "C3").withSkipHeaderRecord(true))) {
1655             printer.printRecord("a", "b", "c");
1656             printer.printRecord("x", "y", "z");
1657             assertEquals("a,b,c\r\nx,y,z\r\n", sw.toString());
1658         }
1659     }
1660 
1661     @Test
1662     public void testTrailingDelimiterOnTwoColumns() throws IOException {
1663         final StringWriter sw = new StringWriter();
1664         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withTrailingDelimiter())) {
1665             printer.printRecord("A", "B");
1666             assertEquals("A,B,\r\n", sw.toString());
1667         }
1668     }
1669 
1670     @Test
1671     public void testTrimOffOneColumn() throws IOException {
1672         final StringWriter sw = new StringWriter();
1673         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withTrim(false))) {
1674             printer.print(" A ");
1675             assertEquals("\" A \"", sw.toString());
1676         }
1677     }
1678 
1679     @Test
1680     public void testTrimOnOneColumn() throws IOException {
1681         final StringWriter sw = new StringWriter();
1682         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withTrim())) {
1683             printer.print(" A ");
1684             assertEquals("A", sw.toString());
1685         }
1686     }
1687 
1688     @Test
1689     public void testTrimOnTwoColumns() throws IOException {
1690         final StringWriter sw = new StringWriter();
1691         try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withTrim())) {
1692             printer.print(" A ");
1693             printer.print(" B ");
1694             assertEquals("A,B", sw.toString());
1695         }
1696     }
1697 
1698     private String[] toFirstRecordValues(final String expected, final CSVFormat format) throws IOException {
1699         return CSVParser.parse(expected, format).getRecords().get(0).values();
1700     }
1701 
1702     private void tryFormat(final List<String> list, final Character quote, final Character escape, final String expected) throws IOException {
1703         final CSVFormat format = CSVFormat.DEFAULT.withQuote(quote).withEscape(escape).withRecordSeparator(null);
1704         final Appendable out = new StringBuilder();
1705         try (final CSVPrinter printer = new CSVPrinter(out, format)) {
1706             printer.printRecord(list);
1707         }
1708         assertEquals(expected, out.toString());
1709     }
1710 }