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