View Javadoc
1   package com.opencsv;
2   
3   /*
4    Copyright 2005 Bytecode Pty Ltd.
5   
6    Licensed under the Apache License, Version 2.0 (the "License");
7    you may not use this file except in compliance with the License.
8    You may obtain a copy of the License at
9   
10   http://www.apache.org/licenses/LICENSE-2.0
11  
12   Unless required by applicable law or agreed to in writing, software
13   distributed under the License is distributed on an "AS IS" BASIS,
14   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   See the License for the specific language governing permissions and
16   limitations under the License.
17   */
18  
19  import com.opencsv.enums.CSVReaderNullFieldIndicator;
20  import com.opencsv.exceptions.CsvException;
21  import com.opencsv.exceptions.CsvValidationException;
22  import com.opencsv.util.MockDataBuilder;
23  import org.junit.jupiter.api.*;
24  
25  import java.io.*;
26  import java.nio.channels.Channels;
27  import java.nio.channels.ReadableByteChannel;
28  import java.nio.charset.StandardCharsets;
29  import java.util.Locale;
30  
31  import static org.junit.jupiter.api.Assertions.*;
32  
33  public class CSVReaderTest {
34  
35      CSVReader csvr;
36      MockDataBuilder mockDataBuilder;
37  
38      private static Locale systemLocale;
39  
40      @BeforeAll
41      public static void storeSystemLocale() {
42          systemLocale = Locale.getDefault();
43      }
44  
45      @AfterEach
46      public void setSystemLocaleBackToDefault() {
47          Locale.setDefault(systemLocale);
48      }
49  
50      @BeforeEach
51      public void setUp() {
52          Locale.setDefault(Locale.US);
53          MockDataBuilder builder = new MockDataBuilder();
54  
55          builder.addDataRow("a,b,c");   // standard case
56          builder.addDataRow("a,\"b,b,b\",c");  // quoted elements
57          builder.addDataRow(",,"); // empty elements
58          builder.addDataRow("a,\"PO Box 123,\nKippax,ACT. 2615.\nAustralia\",d.");
59          builder.addDataRow("\"Glen \"\"The Man\"\" Smith\",Athlete,Developer"); // Test quoted quote chars
60          builder.addDataRow("\"\"\"\"\"\",\"test\""); // """""","test"  representing:  "", test
61          builder.addDataRow("\"a\nb\",b,\"\nd\",e");
62          csvr = new CSVReader(builder.buildStringReader());
63  
64          mockDataBuilder = new MockDataBuilder();
65      }
66  
67  
68      /**
69       * Tests iterating over a reader.
70       *
71       * @throws IOException if the reader fails.
72       */
73      @Test
74      public void testParseLine() throws IOException, CsvValidationException {
75  
76          // test normal case
77          String[] nextLine = csvr.readNext();
78          assertEquals("a", nextLine[0]);
79          assertEquals("b", nextLine[1]);
80          assertEquals("c", nextLine[2]);
81  
82          // test quoted commas
83          nextLine = csvr.readNext();
84          assertEquals("a", nextLine[0]);
85          assertEquals("b,b,b", nextLine[1]);
86          assertEquals("c", nextLine[2]);
87  
88          // test empty elements
89          nextLine = csvr.readNext();
90          assertEquals(3, nextLine.length);
91  
92          // test multiline quoted
93          nextLine = csvr.readNext();
94          assertEquals(3, nextLine.length);
95  
96          // test quoted quote chars
97          nextLine = csvr.readNext();
98          assertEquals("Glen \"The Man\" Smith", nextLine[0]);
99  
100         nextLine = csvr.readNext();
101         assertEquals("\"\"", nextLine[0]); // check the tricky situation
102         assertEquals("test", nextLine[1]); // make sure we didn't ruin the next field..
103 
104         nextLine = csvr.readNext();
105         assertEquals(4, nextLine.length);
106 
107         //test end of stream
108         assertNull(csvr.readNext());
109     }
110 
111     @Test
112     public void readerCanHandleNullInString() throws IOException, CsvValidationException {
113 
114         mockDataBuilder.addDataRow("a,\0b,c");
115 
116         CSVReaderBuilder builder = new CSVReaderBuilder(mockDataBuilder.buildStringReader());
117         CSVReader defaultReader = builder.build();
118 
119         String[] nextLine = defaultReader.readNext();
120         assertEquals(3, nextLine.length);
121         assertEquals("a", nextLine[0]);
122         assertEquals("\0b", nextLine[1]);
123         assertEquals(0, nextLine[1].charAt(0));
124         assertEquals("c", nextLine[2]);
125     }
126 
127     @Test
128     public void testParseLineStrictQuote() throws IOException, CsvValidationException {
129 
130         mockDataBuilder.addDataRow("a,b,c");   // standard case
131         mockDataBuilder.addDataRow("a,\"b,b,b\",c");  // quoted elements
132         mockDataBuilder.addDataRow(",,"); // empty elements
133         mockDataBuilder.addDataRow("a,\"PO Box 123,\nKippax,ACT. 2615.\nAustralia\",d.");
134         mockDataBuilder.addDataRow("\"Glen \"\"The Man\"\" Smith\",Athlete,Developer"); // Test quoted quote chars
135         mockDataBuilder.addDataRow("\"\"\"\"\"\",\"test\""); // """""","test"  representing:  "", test
136         mockDataBuilder.addDataRow("\"a\nb\",b,\"\nd\",e");
137         csvr = new CSVReaderBuilder(mockDataBuilder.buildStringReader())
138                 .withCSVParser(new CSVParserBuilder()
139                         .withStrictQuotes(true)
140                         .build())
141                 .build();
142 
143         // test normal case
144         String[] nextLine = csvr.readNext();
145         assertEquals("", nextLine[0]);
146         assertEquals("", nextLine[1]);
147         assertEquals("", nextLine[2]);
148 
149         // test quoted commas
150         nextLine = csvr.readNext();
151         assertEquals("", nextLine[0]);
152         assertEquals("b,b,b", nextLine[1]);
153         assertEquals("", nextLine[2]);
154 
155         // test empty elements
156         nextLine = csvr.readNext();
157         assertEquals(3, nextLine.length);
158 
159         // test multiline quoted
160         nextLine = csvr.readNext();
161         assertEquals(3, nextLine.length);
162 
163         // test quoted quote chars
164         nextLine = csvr.readNext();
165         assertEquals("Glen \"The Man\" Smith", nextLine[0]);
166 
167         nextLine = csvr.readNext();
168         assertEquals("\"\"", nextLine[0]); // check the tricky situation
169         assertEquals("test", nextLine[1]); // make sure we didn't ruin the next field..
170 
171         nextLine = csvr.readNext();
172         assertEquals(4, nextLine.length);
173         assertEquals("a\nb", nextLine[0]);
174         assertEquals("", nextLine[1]);
175         assertEquals("\nd", nextLine[2]);
176         assertEquals("", nextLine[3]);
177 
178         //test end of stream
179         assertNull(csvr.readNext());
180     }
181 
182 
183     /**
184      * Test parsing to a list.
185      *
186      * @throws IOException if the reader fails.
187      */
188     @Test
189     public void testParseAll() throws IOException, CsvException {
190         assertEquals(7, csvr.readAll().size());
191     }
192 
193     /**
194      * Tests constructors with non-default delimiter and quote char.
195      *
196      * @throws IOException if the reader fails.
197      */
198     @Test
199     public void testOptionalConstructors() throws IOException, CsvValidationException {
200 
201         mockDataBuilder.addDataRow("a\tb\tc");   // tab separated case
202         mockDataBuilder.addDataRow("a\t'b\tb\tb'\tc");  // single quoted elements
203         CSVReader c = new CSVReaderBuilder(mockDataBuilder.buildStringReader())
204                 .withCSVParser(new CSVParserBuilder()
205                         .withQuoteChar('\'')
206                         .withSeparator('\t')
207                         .build())
208                 .build();
209 
210         String[] nextLine = c.readNext();
211         assertEquals(3, nextLine.length);
212 
213         nextLine = c.readNext();
214         assertEquals(3, nextLine.length);
215     }
216 
217     @Test
218     public void parseQuotedStringWithDefinedSeparator() throws IOException, CsvValidationException {
219 
220         mockDataBuilder.addDataRow("a\tb\tc");   // tab separated case
221 
222         CSVReader c = new CSVReaderBuilder(mockDataBuilder.buildStringReader())
223                 .withCSVParser(new CSVParserBuilder()
224                         .withSeparator('\t')
225                         .build())
226                 .build();
227 
228         String[] nextLine = c.readNext();
229         assertEquals(3, nextLine.length);
230     }
231 
232     /**
233      * Tests option to skip the first few lines of a file.
234      *
235      * @throws IOException if bad things happen
236      */
237     @Test
238     public void testSkippingLines() throws IOException, CsvValidationException {
239 
240         mockDataBuilder.addDataRow("Skip this line\t with tab");   // should skip this
241         mockDataBuilder.addDataRow("And this line too");   // and this
242         mockDataBuilder.addDataRow("a\t'b\tb\tb'\tc");  // single quoted elements
243         CSVReader c = new CSVReaderBuilder(mockDataBuilder.buildStringReader())
244                 .withCSVParser(new CSVParserBuilder()
245                         .withQuoteChar('\'')
246                         .withSeparator('\t')
247                         .build())
248                 .withSkipLines(2)
249                 .build();
250 
251         String[] nextLine = c.readNext();
252         assertEquals(3, nextLine.length);
253 
254         assertEquals("a", nextLine[0]);
255     }
256 
257     /**
258      * Tests methods to get the number of lines and records read.
259      *
260      * @throws IOException if bad things happen
261      */
262     @Test
263     public void linesAndRecordsRead() throws IOException, CsvValidationException {
264 
265         mockDataBuilder.addDataRow("Skip this line\t with tab");   // should skip this
266         mockDataBuilder.addDataRow("And this line too");   // and this
267         mockDataBuilder.addDataRow("a,b,c");  // second line
268         mockDataBuilder.addDataRow("");                  // no data here just a blank line
269         mockDataBuilder.addDataRow("a,\"b\nb\",c");
270 
271         CSVReaderBuilder builder = new CSVReaderBuilder(mockDataBuilder.buildStringReader());
272         CSVReader c = builder.withCSVParser(new CSVParser())
273                 .withSkipLines(2)
274                 .build();
275 
276         assertEquals(0, c.getLinesRead());
277         assertEquals(0, c.getRecordsRead());
278 
279         String[] nextLine = c.readNext();
280         assertEquals(3, nextLine.length);
281 
282         assertEquals(3, c.getLinesRead());
283         assertEquals(1, c.getRecordsRead());
284 
285         nextLine = c.readNext();
286         assertEquals(1, nextLine.length);
287         assertEquals(0, nextLine[0].length());
288 
289         assertEquals(4, c.getLinesRead());
290         assertEquals(2, c.getRecordsRead());  // A blank line is considered a record with a single element
291 
292         nextLine = c.readNext();
293         assertEquals(3, nextLine.length);
294 
295         assertEquals(6, c.getLinesRead());
296         assertEquals(3, c.getRecordsRead());  // two lines read to get a single record.
297 
298         nextLine = c.readNext();  // reading after all the data has been read.
299         assertNull(nextLine);
300 
301         assertEquals(6, c.getLinesRead());
302         assertEquals(3, c.getRecordsRead());
303     }
304 
305     /**
306      * Tests option to skip the first few lines of a file.
307      *
308      * @throws IOException if bad things happen
309      */
310     @Test
311     public void testSkippingLinesWithDifferentEscape() throws IOException, CsvValidationException {
312 
313         mockDataBuilder.addDataRow("Skip this line?t with tab");   // should skip this
314         mockDataBuilder.addDataRow("And this line too");   // and this
315         mockDataBuilder.addDataRow("a\t'b\tb\tb'\t'c'");  // single quoted elements
316         CSVReader c = new CSVReaderBuilder(mockDataBuilder.buildStringReader())
317                 .withCSVParser(new CSVParserBuilder()
318                         .withQuoteChar('\'')
319                         .withSeparator('\t')
320                         .withEscapeChar('?')
321                         .build())
322                 .withSkipLines(2)
323                 .build();
324 
325         String[] nextLine = c.readNext();
326 
327         assertEquals(3, nextLine.length);
328 
329         assertEquals("a", nextLine[0]);
330         assertEquals("b\tb\tb", nextLine[1]);
331         assertEquals("c", nextLine[2]);
332     }
333 
334     /**
335      * Test a normal non quoted line with three elements
336      *
337      * @throws IOException But not really
338      */
339     @Test
340     public void testNormalParsedLine() throws IOException, CsvValidationException {
341         mockDataBuilder.addDataRow("a,1234567,c");// a,1234,c
342 
343         try (CSVReader c = new CSVReader(mockDataBuilder.buildStringReader())) {
344             String[] nextLine = c.readNext();
345             assertEquals(3, nextLine.length);
346 
347             assertEquals("a", nextLine[0]);
348             assertEquals("1234567", nextLine[1]);
349             assertEquals("c", nextLine[2]);
350         }
351     }
352 
353 
354     /**
355      * Same as testADoubleQuoteAsDataElement but I changed the quotechar to a
356      * single quote.
357      *
358      * @throws IOException But not really
359      */
360     @Test
361     public void testASingleQuoteAsDataElement() throws IOException, CsvValidationException {
362 
363         mockDataBuilder.addDataRow("a,'''',c");// a,',c
364 
365         CSVReader c = new CSVReaderBuilder(mockDataBuilder.buildStringReader())
366                 .withCSVParser(new CSVParserBuilder()
367                         .withQuoteChar('\'')
368                         .withSeparator(',')
369                         .build())
370                 .build();
371 
372         String[] nextLine = c.readNext();
373         assertEquals(3, nextLine.length);
374 
375         assertEquals("a", nextLine[0]);
376         assertEquals(1, nextLine[1].length());
377         assertEquals("'", nextLine[1]);
378         assertEquals("c", nextLine[2]);
379     }
380 
381     /**
382      * Same as testADoubleQuoteAsDataElement but I changed the quotechar to a
383      * single quote.  Also the middle field is empty.
384      *
385      * @throws IOException But not really
386      */
387     @Test
388     public void testASingleQuoteAsDataElementWithEmptyField() throws IOException, CsvValidationException {
389 
390         mockDataBuilder.addDataRow("a,'',c");// a,,c
391 
392         CSVReader c = new CSVReaderBuilder(mockDataBuilder.buildStringReader())
393                 .withCSVParser(new CSVParserBuilder()
394                         .withQuoteChar('\'')
395                         .withSeparator(',')
396                         .build())
397                 .build();
398 
399         String[] nextLine = c.readNext();
400         assertEquals(3, nextLine.length);
401 
402         assertEquals("a", nextLine[0]);
403         assertEquals(0, nextLine[1].length());
404         assertEquals("", nextLine[1]);
405         assertEquals("c", nextLine[2]);
406     }
407 
408     @Test
409     public void testSpacesAtEndOfString() throws IOException, CsvValidationException {
410         mockDataBuilder.addDataRow("\"a\",\"b\",\"c\"   ");
411 
412         CSVReader c = new CSVReaderBuilder(mockDataBuilder.buildStringReader())
413                 .withCSVParser(new CSVParserBuilder()
414                         .withStrictQuotes(true)
415                         .build())
416                 .build();
417 
418         String[] nextLine = c.readNext();
419         assertEquals(3, nextLine.length);
420 
421         assertEquals("a", nextLine[0]);
422         assertEquals("b", nextLine[1]);
423         assertEquals("c", nextLine[2]);
424     }
425 
426 
427     @Test
428     public void testEscapedQuote() throws IOException, CsvValidationException {
429         mockDataBuilder.addDataRow("a,\"123\\\"4567\",c");// a,123"4",c
430 
431         try (CSVReader c = new CSVReader(mockDataBuilder.buildStringReader())) {
432             String[] nextLine = c.readNext();
433             assertEquals(3, nextLine.length);
434 
435             assertEquals("123\"4567", nextLine[1]);
436         }
437     }
438 
439     @Test
440     public void testEscapedEscape() throws IOException, CsvValidationException {
441         mockDataBuilder.addDataRow("a,\"123\\\\4567\",c");// a,123"4",c
442 
443         try (CSVReader c = new CSVReader(mockDataBuilder.buildStringReader())) {
444             String[] nextLine = c.readNext();
445             assertEquals(3, nextLine.length);
446 
447             assertEquals("123\\4567", nextLine[1]);
448         }
449     }
450 
451 
452     /**
453      * Test a line where one of the elements is two single quotes and the
454      * quote character is the default double quote.  The expected result is two
455      * single quotes.
456      *
457      * @throws IOException But not really
458      */
459     @Test
460     public void testSingleQuoteWhenDoubleQuoteIsQuoteChar() throws IOException, CsvValidationException {
461         mockDataBuilder.addDataRow("a,'',c");// a,'',c
462 
463         try (CSVReader c = new CSVReader(mockDataBuilder.buildStringReader())) {
464             String[] nextLine = c.readNext();
465             assertEquals(3, nextLine.length);
466 
467             assertEquals("a", nextLine[0]);
468             assertEquals(2, nextLine[1].length());
469             assertEquals("''", nextLine[1]);
470             assertEquals("c", nextLine[2]);
471         }
472     }
473 
474     /**
475      * Test a normal line with three elements and all elements are quoted
476      *
477      * @throws IOException But not really
478      */
479     @Test
480     public void testQuotedParsedLine() throws IOException, CsvValidationException {
481         mockDataBuilder.addDataRow("\"a\",\"1234567\",\"c\""); // "a","1234567","c"
482 
483         CSVReader c = new CSVReaderBuilder(mockDataBuilder.buildStringReader())
484                 .withCSVParser(new CSVParserBuilder()
485                         .withStrictQuotes(true)
486                         .build())
487                 .build();
488 
489         String[] nextLine = c.readNext();
490         assertEquals(3, nextLine.length);
491 
492         assertEquals("a", nextLine[0]);
493         assertEquals(1, nextLine[0].length());
494 
495         assertEquals("1234567", nextLine[1]);
496         assertEquals("c", nextLine[2]);
497     }
498 
499     @Test
500     public void bug106ParseLineWithCarriageReturnNewLineStrictQuotes() throws IOException, CsvValidationException {
501         mockDataBuilder.addDataRow("\"a\",\"123\r\n4567\",\"c\""); // "a","123\r\n4567","c"
502 
503         // public CSVReader(Reader reader, char separator, char quotechar, char escape, int line, boolean strictQuotes,
504         // boolean ignoreLeadingWhiteSpace, boolean keepCarriageReturn)
505         CSVReader c = new CSVReaderBuilder(mockDataBuilder.buildStringReader())
506                 .withCSVParser(new CSVParserBuilder()
507                         .withStrictQuotes(true)
508                         .build())
509                 .withKeepCarriageReturn(true)
510                 .build();
511 
512         String[] nextLine = c.readNext();
513         assertEquals(3, nextLine.length);
514 
515         assertEquals("a", nextLine[0]);
516         assertEquals(1, nextLine[0].length());
517 
518         assertEquals("123\r\n4567", nextLine[1]);
519         assertEquals("c", nextLine[2]);
520     }
521 
522     @Test
523     public void bug233KeepCarriageReturnShouldRemoveCRAtEndOfLine() throws IOException, CsvValidationException {
524          StringBuilder sb = new StringBuilder(ICSVParser.INITIAL_READ_SIZE);
525 
526         sb.append("\"a\",\"123\r\n4567\",c");
527         sb.append("\r\n");
528 
529         // public CSVReader(Reader reader, char separator, char quotechar, char escape, int line, boolean strictQuotes,
530         // boolean ignoreLeadingWhiteSpace, boolean keepCarriageReturn)
531         CSVReader c = new CSVReaderBuilder(new StringReader(sb.toString()))
532                 .withCSVParser(new CSVParserBuilder()
533                         .withStrictQuotes(false)
534                         .build())
535                 .withKeepCarriageReturn(true)
536                 .build();
537 
538         String[] nextLine = c.readNext();
539         assertEquals(3, nextLine.length);
540 
541         assertEquals("a", nextLine[0]);
542         assertEquals(1, nextLine[0].length());
543 
544         assertEquals("123\r\n4567", nextLine[1]);
545         assertFalse(nextLine[2].endsWith("\r"));
546         assertEquals("c", nextLine[2]);
547     }
548 
549     @Test
550     public void testIssue2992134OutOfPlaceQuotes() throws IOException, CsvValidationException {
551         mockDataBuilder.addDataRow("a,b,c,ddd\\\"eee\nf,g,h,\"iii,jjj\"");
552 
553         try (CSVReader c = new CSVReader(mockDataBuilder.buildStringReader())) {
554             String[] nextLine = c.readNext();
555 
556             assertEquals("a", nextLine[0]);
557             assertEquals("b", nextLine[1]);
558             assertEquals("c", nextLine[2]);
559             assertEquals("ddd\"eee", nextLine[3]);
560         }
561     }
562 
563     @Test
564     public void quoteAndEscapeMustBeDifferent() {
565         mockDataBuilder.addDataRow("a,b,c,ddd\\\"eee\nf,g,h,\"iii,jjj\"");
566 
567         Assertions.assertThrows(UnsupportedOperationException.class, () -> {
568             new CSVReaderBuilder(mockDataBuilder.buildStringReader())
569                     .withCSVParser(new CSVParserBuilder()
570                             .withEscapeChar(ICSVParser.DEFAULT_QUOTE_CHARACTER)
571                             .build())
572                     .build();
573         });
574     }
575 
576     @Test
577     public void separatorAndEscapeMustBeDifferent() {
578         mockDataBuilder.addDataRow("a,b,c,ddd\\\"eee\nf,g,h,\"iii,jjj\"");
579 
580         Assertions.assertThrows(UnsupportedOperationException.class, () -> {
581             new CSVReaderBuilder(mockDataBuilder.buildStringReader())
582                     .withCSVParser(new CSVParserBuilder()
583                             .withEscapeChar(ICSVParser.DEFAULT_SEPARATOR)
584                             .build())
585                     .build();
586         });
587     }
588 
589     @Test
590     public void separatorAndQuoteMustBeDifferent() {
591         mockDataBuilder.addDataRow("a,b,c,ddd\\\"eee\nf,g,h,\"iii,jjj\"");
592 
593         Assertions.assertThrows(UnsupportedOperationException.class, () -> {
594             new CSVReaderBuilder(mockDataBuilder.buildStringReader())
595                     .withCSVParser(new CSVParserBuilder()
596                             .withQuoteChar(ICSVParser.DEFAULT_SEPARATOR)
597                             .build())
598                     .build();
599         });
600     }
601 
602     /**
603      * Tests iterating over a reader.
604      */
605     @Test
606     public void testIteratorFunctionality() {
607         String[][] expectedResult = new String[7][];
608         expectedResult[0] = new String[]{"a", "b", "c"};
609         expectedResult[1] = new String[]{"a", "b,b,b", "c"};
610         expectedResult[2] = new String[]{"", "", ""};
611         expectedResult[3] = new String[]{"a", "PO Box 123,\nKippax,ACT. 2615.\nAustralia", "d."};
612         expectedResult[4] = new String[]{"Glen \"The Man\" Smith", "Athlete", "Developer"};
613         expectedResult[5] = new String[]{"\"\"", "test"};
614         expectedResult[6] = new String[]{"a\nb", "b", "\nd", "e"};
615         int idx = 0;
616         for (String[] line : csvr) {
617             String[] expectedLine = expectedResult[idx++];
618             assertArrayEquals(expectedLine, line);
619         }
620     }
621 
622     @Test
623     public void testIteratorWithBadReader() {
624         CSVReader r = new CSVReaderBuilder(new StringReader("This,is,a,\"test\na\",test"))
625                 .withMultilineLimit(1).build();
626         String englishErrorMessage = null;
627         try {
628             for (String[] line : r) {}
629             fail("The Reader should always throw an exception.");
630         }
631         catch(RuntimeException re) {
632             assertNotNull(re.getCause());
633             assertTrue(re.getCause() instanceof IOException);
634             englishErrorMessage = re.getCause().getLocalizedMessage();
635         }
636         
637         // Now with a different locale
638         r = new CSVReaderBuilder(new StringReader("This,is,a,\"test\na\",test"))
639                 .withMultilineLimit(1).withErrorLocale(Locale.GERMAN).build();
640         try {
641             for (String[] line : r) {}
642             fail("The Reader should always throw an exception.");
643         }
644         catch(RuntimeException re) {
645             assertNotNull(re.getCause());
646             assertTrue(re.getCause() instanceof IOException);
647             assertNotSame(englishErrorMessage, re.getCause().getLocalizedMessage());
648         }
649     }
650 
651     @Test
652     public void canCloseReader() throws IOException {
653         csvr.close();
654     }
655 
656     @Test
657     public void canCreateIteratorFromReader() {
658         assertNotNull(csvr.iterator());
659     }
660 
661     @Test
662     public void attemptToReadCloseStreamReturnsNull() throws IOException, CsvValidationException {
663         BufferedReader bufferedReader = new BufferedReader(new StringReader(""));
664         bufferedReader.close();
665         try (CSVReader csvReader = new CSVReader(bufferedReader)) {
666             assertNull(csvReader.readNext());
667         }
668     }
669 
670     @Test
671     public void testIssue102() throws IOException, CsvValidationException {
672         try (CSVReader csvReader = new CSVReader(new StringReader("\"\",a\n\"\",b\n"))) {
673             String[] firstRow = csvReader.readNext();
674             assertEquals(2, firstRow.length);
675             assertTrue(firstRow[0].isEmpty());
676             assertEquals("a", firstRow[1]);
677 
678             String[] secondRow = csvReader.readNext();
679             assertEquals(2, secondRow.length);
680             assertTrue(secondRow[0].isEmpty());
681             assertEquals("b", secondRow[1]);
682         }
683     }
684 
685     @Test
686     public void issue108ReaderPlaysWellWithChannels() throws IOException, CsvException {
687         byte[] bytes = "name\r\nvalue\r\n".getBytes(StandardCharsets.UTF_8);
688         ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
689         ReadableByteChannel ch = Channels.newChannel(bais);
690         InputStream in = Channels.newInputStream(ch);
691         InputStreamReader reader = new InputStreamReader(in, StandardCharsets.UTF_8);
692         CSVReaderBuilder builder = new CSVReaderBuilder(reader);
693         CSVReader csv = builder.withVerifyReader(false).build();
694         assertEquals(2, csv.readAll().size());
695     }
696 
697     @Test
698     public void featureRequest60ByDefaultEmptyFieldsAreBlank() throws IOException, CsvValidationException {
699         mockDataBuilder.addDataRow(",,,\"\",");
700 
701         CSVReaderBuilder builder = new CSVReaderBuilder(mockDataBuilder.buildStringReader());
702         CSVReader csvReader = builder.build();
703 
704         String[] row = csvReader.readNext();
705 
706         assertEquals(5, row.length);
707         assertEquals("", row[0]);
708         assertEquals("", row[1]);
709         assertEquals("", row[2]);
710         assertEquals("", row[3]);
711         assertEquals("", row[4]);
712     }
713 
714     @Test
715     public void featureRequest60TreatEmptyFieldsAsNull() throws IOException, CsvValidationException {
716 
717         mockDataBuilder.addDataRow(",,,\"\",");
718         CSVReaderBuilder builder = new CSVReaderBuilder(mockDataBuilder.buildStringReader());
719 
720         CSVReader csvReader = builder.withFieldAsNull(CSVReaderNullFieldIndicator.EMPTY_SEPARATORS).build();
721 
722         String[] item = csvReader.readNext();
723 
724         assertEquals(5, item.length);
725         assertNull(item[0]);
726         assertNull(item[1]);
727         assertNull(item[2]);
728         assertEquals("", item[3]);
729         assertNull(item[4]);
730 
731     }
732 
733     @Test
734     public void featureRequest60TreatEmptyDelimitedFieldsAsNull() throws IOException, CsvValidationException {
735         mockDataBuilder.addDataRow(",,,\"\",");
736 
737         CSVReaderBuilder builder = new CSVReaderBuilder(mockDataBuilder.buildStringReader());
738         CSVReader csvReader = builder.withFieldAsNull(CSVReaderNullFieldIndicator.EMPTY_QUOTES).build();
739 
740         String[] item = csvReader.readNext();
741 
742         assertEquals(5, item.length);
743         assertEquals("", item[0]);
744         assertEquals("", item[1]);
745         assertEquals("", item[2]);
746         assertNull(item[3]);
747         assertEquals("", item[4]);
748     }
749 
750     @Test
751     public void featureRequest60TreatEmptyFieldsDelimitedOrNotAsNull() throws IOException, CsvValidationException {
752         mockDataBuilder.addDataRow(",,,\"\",");
753         CSVReaderBuilder builder = new CSVReaderBuilder(mockDataBuilder.buildStringReader());
754         CSVReader csvReader = builder.withFieldAsNull(CSVReaderNullFieldIndicator.BOTH).build();
755 
756         String[] item = csvReader.readNext();
757 
758         assertEquals(5, item.length);
759         assertNull(item[0]);
760         assertNull(item[1]);
761         assertNull(item[2]);
762         assertNull(item[3]);
763         assertNull(item[4]);
764     }
765 
766     @Test
767     public void testMultilineLimit() {
768         CSVReader r = new CSVReaderBuilder(new StringReader("This,is,a,\"test\na\",test"))
769                 .withMultilineLimit(1).build();
770         Assertions.assertThrows(IOException.class, () -> r.readNext());
771     }
772 
773     @Test
774     public void testReadMultilineClosingQuoteMissing() throws CsvValidationException {
775         final String part1 = "This,is,a,\"";
776         final String part2 = "test\na,test";
777         try (CSVReader r = new CSVReader(new StringReader(part1+part2))) {
778             try {
779                 r.readNext();
780                 fail("Exception should have been thrown.");
781             }
782             catch(IOException e) {
783                 assertTrue(e.getMessage().contains(part2));
784             }
785         } catch (IOException _ex) {
786             fail("No exception should have been thrown.");
787         }
788     }
789     
790     @Test
791     public void testPeek() throws IOException, CsvValidationException {
792         String[] peeked = csvr.peek();
793         assertArrayEquals(peeked, csvr.peek());
794         assertArrayEquals(peeked, csvr.peek());
795         assertArrayEquals(peeked, csvr.readNext());
796         assertNotSame(peeked[1], csvr.readNext()[1]);
797     }
798 }