1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.commons.csv;
21
22 import static org.apache.commons.csv.Constants.CR;
23 import static org.apache.commons.csv.Constants.CRLF;
24 import static org.apache.commons.csv.Constants.LF;
25 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
26 import static org.junit.jupiter.api.Assertions.assertEquals;
27 import static org.junit.jupiter.api.Assertions.assertFalse;
28 import static org.junit.jupiter.api.Assertions.assertInstanceOf;
29 import static org.junit.jupiter.api.Assertions.assertNotNull;
30 import static org.junit.jupiter.api.Assertions.assertNull;
31 import static org.junit.jupiter.api.Assertions.assertThrows;
32 import static org.junit.jupiter.api.Assertions.assertTrue;
33
34 import java.io.File;
35 import java.io.IOException;
36 import java.io.InputStreamReader;
37 import java.io.PipedReader;
38 import java.io.PipedWriter;
39 import java.io.Reader;
40 import java.io.StringReader;
41 import java.io.StringWriter;
42 import java.io.UncheckedIOException;
43 import java.net.URL;
44 import java.nio.charset.Charset;
45 import java.nio.charset.StandardCharsets;
46 import java.nio.file.Files;
47 import java.nio.file.Path;
48 import java.nio.file.Paths;
49 import java.util.ArrayList;
50 import java.util.Arrays;
51 import java.util.Iterator;
52 import java.util.List;
53 import java.util.Map;
54 import java.util.NoSuchElementException;
55 import java.util.stream.Collectors;
56 import java.util.stream.Stream;
57
58 import org.apache.commons.io.input.BOMInputStream;
59 import org.apache.commons.io.input.BrokenInputStream;
60 import org.junit.jupiter.api.Assertions;
61 import org.junit.jupiter.api.Disabled;
62 import org.junit.jupiter.api.Test;
63 import org.junit.jupiter.params.ParameterizedTest;
64 import org.junit.jupiter.params.provider.EnumSource;
65
66
67
68
69
70
71
72 public class CSVParserTest {
73
74 private static final CSVFormat EXCEL_WITH_HEADER = CSVFormat.EXCEL.withHeader();
75
76 private static final Charset UTF_8 = StandardCharsets.UTF_8;
77
78 private static final String UTF_8_NAME = UTF_8.name();
79
80 private static final String CSV_INPUT = "a,b,c,d\n" + " a , b , 1 2 \n" + "\"foo baar\", b,\n" +
81
82 " \"foo\n,,\n\"\",,\n\"\"\",d,e\n";
83
84 private static final String CSV_INPUT_1 = "a,b,c,d";
85
86 private static final String CSV_INPUT_2 = "a,b,1 2";
87
88 private static final String[][] RESULT = { { "a", "b", "c", "d" }, { "a", "b", "1 2" }, { "foo baar", "b", "" }, { "foo\n,,\n\",,\n\"", "d", "e" } };
89
90
91 private static final String CSV_INPUT_NO_COMMENT = "A,B" + CRLF + "1,2" + CRLF;
92
93
94 private static final String CSV_INPUT_HEADER_COMMENT = "# header comment" + CRLF + "A,B" + CRLF + "1,2" + CRLF;
95
96
97 private static final String CSV_INPUT_HEADER_TRAILER_COMMENT = "# header comment" + CRLF + "A,B" + CRLF + "1,2" + CRLF + "# comment";
98
99
100 private static final String CSV_INPUT_MULTILINE_HEADER_TRAILER_COMMENT = "# multi-line" + CRLF + "# header comment" + CRLF + "A,B" + CRLF + "1,2" + CRLF +
101 "# multi-line" + CRLF + "# comment";
102
103
104 private static final CSVFormat FORMAT_AUTO_HEADER = CSVFormat.Builder.create(CSVFormat.DEFAULT).setCommentMarker('#').setHeader().get();
105
106
107
108 private static final CSVFormat FORMAT_EXPLICIT_HEADER = CSVFormat.Builder.create(CSVFormat.DEFAULT)
109 .setSkipHeaderRecord(true)
110 .setCommentMarker('#')
111 .setHeader("A", "B")
112 .get();
113
114
115
116
117 CSVFormat FORMAT_EXPLICIT_HEADER_NOSKIP = CSVFormat.Builder.create(CSVFormat.DEFAULT)
118 .setCommentMarker('#')
119 .setHeader("A", "B")
120 .get();
121
122
123 @SuppressWarnings("resource")
124 private BOMInputStream createBOMInputStream(final String resource) throws IOException {
125 return new BOMInputStream(ClassLoader.getSystemClassLoader().getResource(resource).openStream());
126 }
127
128 CSVRecord parse(final CSVParser parser, final int failParseRecordNo) throws IOException {
129 if (parser.getRecordNumber() + 1 == failParseRecordNo) {
130 assertThrows(IOException.class, () -> parser.nextRecord());
131 return null;
132 }
133 return parser.nextRecord();
134 }
135
136 private void parseFully(final CSVParser parser) {
137 parser.forEach(Assertions::assertNotNull);
138 }
139
140 @Test
141 public void testBackslashEscaping() throws IOException {
142
143
144
145
146
147 final String code = "one,two,three\n" +
148 "'',''\n" +
149 "/',/'\n" +
150 "'/'','/''\n" +
151 "'''',''''\n" +
152 "/,,/,\n" +
153 "//,//\n" + // 6) escape escaped
154 "'//','//'\n" + // 7) escape escaped in encapsulation
155 " 8 , \"quoted \"\" /\" // string\" \n" + // don't eat spaces
156 "9, /\n \n" +
157 "";
158 final String[][] res = {{"one", "two", "three"},
159 {"", ""},
160 {"'", "'"},
161 {"'", "'"},
162 {"'", "'"},
163 {",", ","},
164 {"/", "/"},
165 {"/", "/"},
166 {" 8 ", " \"quoted \"\" /\" / string\" "}, {"9", " \n "} };
167
168 final CSVFormat format = CSVFormat.newFormat(',').withQuote('\'').withRecordSeparator(CRLF).withEscape('/').withIgnoreEmptyLines();
169 try (CSVParser parser = CSVParser.parse(code, format)) {
170 final List<CSVRecord> records = parser.getRecords();
171 assertFalse(records.isEmpty());
172 Utils.compare("Records do not match expected result", res, records);
173 }
174 }
175
176 @Test
177 public void testBackslashEscaping2() throws IOException {
178
179
180
181
182 final String code = "" + " , , \n" +
183 " \t , , \n" +
184 " // , /, , /,\n" + // 3)
185 "";
186 final String[][] res = {{" ", " ", " "},
187 {" \t ", " ", " "},
188 {" / ", " , ", " ,"},
189 };
190
191 final CSVFormat format = CSVFormat.newFormat(',').withRecordSeparator(CRLF).withEscape('/').withIgnoreEmptyLines();
192 try (CSVParser parser = CSVParser.parse(code, format)) {
193 final List<CSVRecord> records = parser.getRecords();
194 assertFalse(records.isEmpty());
195 Utils.compare("", res, records);
196 }
197 }
198
199 @Test
200 @Disabled
201 public void testBackslashEscapingOld() throws IOException {
202 final String code = "one,two,three\n" + "on\\\"e,two\n" + "on\"e,two\n" + "one,\"tw\\\"o\"\n" + "one,\"t\\,wo\"\n" + "one,two,\"th,ree\"\n" +
203 "\"a\\\\\"\n" + "a\\,b\n" + "\"a\\\\,b\"";
204 final String[][] res = { { "one", "two", "three" }, { "on\\\"e", "two" }, { "on\"e", "two" }, { "one", "tw\"o" }, { "one", "t\\,wo" },
205
206
207
208
209 { "one", "two", "th,ree" }, { "a\\\\" },
210 { "a\\", "b" },
211 { "a\\\\,b" }
212 };
213 try (CSVParser parser = CSVParser.parse(code, CSVFormat.DEFAULT)) {
214 final List<CSVRecord> records = parser.getRecords();
215 assertEquals(res.length, records.size());
216 assertFalse(records.isEmpty());
217 for (int i = 0; i < res.length; i++) {
218 assertArrayEquals(res[i], records.get(i).values());
219 }
220 }
221 }
222
223 @Test
224 @Disabled("CSV-107")
225 public void testBOM() throws IOException {
226 final URL url = ClassLoader.getSystemClassLoader().getResource("org/apache/commons/csv/CSVFileParser/bom.csv");
227 try (CSVParser parser = CSVParser.parse(url, StandardCharsets.UTF_8, EXCEL_WITH_HEADER)) {
228 parser.forEach(record -> assertNotNull(record.get("Date")));
229 }
230 }
231
232 @Test
233 public void testBOMInputStreamParserWithInputStream() throws IOException {
234 try (BOMInputStream inputStream = createBOMInputStream("org/apache/commons/csv/CSVFileParser/bom.csv");
235 CSVParser parser = CSVParser.parse(inputStream, UTF_8, EXCEL_WITH_HEADER)) {
236 parser.forEach(record -> assertNotNull(record.get("Date")));
237 }
238 }
239
240 @Test
241 public void testBOMInputStreamParserWithReader() throws IOException {
242 try (Reader reader = new InputStreamReader(createBOMInputStream("org/apache/commons/csv/CSVFileParser/bom.csv"), UTF_8_NAME);
243 CSVParser parser = CSVParser.builder()
244 .setReader(reader)
245 .setFormat(EXCEL_WITH_HEADER)
246 .get()) {
247 parser.forEach(record -> assertNotNull(record.get("Date")));
248 }
249 }
250
251 @Test
252 public void testBOMInputStreamParseWithReader() throws IOException {
253 try (Reader reader = new InputStreamReader(createBOMInputStream("org/apache/commons/csv/CSVFileParser/bom.csv"), UTF_8_NAME);
254 CSVParser parser = CSVParser.builder()
255 .setReader(reader)
256 .setFormat(EXCEL_WITH_HEADER)
257 .get()) {
258 parser.forEach(record -> assertNotNull(record.get("Date")));
259 }
260 }
261
262 @Test
263 public void testCarriageReturnEndings() throws IOException {
264 final String string = "foo\rbaar,\rhello,world\r,kanu";
265 try (CSVParser parser = CSVParser.builder().setCharSequence(string).get()) {
266 final List<CSVRecord> records = parser.getRecords();
267 assertEquals(4, records.size());
268 }
269 }
270
271 @Test
272 public void testCarriageReturnLineFeedEndings() throws IOException {
273 final String string = "foo\r\nbaar,\r\nhello,world\r\n,kanu";
274 try (CSVParser parser = CSVParser.builder().setCharSequence(string).get()) {
275 final List<CSVRecord> records = parser.getRecords();
276 assertEquals(4, records.size());
277 }
278 }
279
280 @Test
281 public void testClose() throws Exception {
282 final Reader in = new StringReader("# comment\na,b,c\n1,2,3\nx,y,z");
283 final Iterator<CSVRecord> records;
284 try (CSVParser parser = CSVFormat.DEFAULT.withCommentMarker('#').withHeader().parse(in)) {
285 records = parser.iterator();
286 assertTrue(records.hasNext());
287 }
288 assertFalse(records.hasNext());
289 assertThrows(NoSuchElementException.class, records::next);
290 }
291
292 @Test
293 public void testCSV141CSVFormat_DEFAULT() throws Exception {
294 testCSV141Failure(CSVFormat.DEFAULT, 3);
295 }
296
297 @Test
298 public void testCSV141CSVFormat_INFORMIX_UNLOAD() throws Exception {
299 testCSV141Failure(CSVFormat.INFORMIX_UNLOAD, 1);
300 }
301
302 @Test
303 public void testCSV141CSVFormat_INFORMIX_UNLOAD_CSV() throws Exception {
304 testCSV141Failure(CSVFormat.INFORMIX_UNLOAD_CSV, 3);
305 }
306
307 @Test
308 public void testCSV141CSVFormat_ORACLE() throws Exception {
309 testCSV141Failure(CSVFormat.ORACLE, 2);
310 }
311
312 @Test
313 public void testCSV141CSVFormat_POSTGRESQL_CSV() throws Exception {
314 testCSV141Failure(CSVFormat.POSTGRESQL_CSV, 3);
315 }
316
317 @Test
318 public void testCSV141Excel() throws Exception {
319 testCSV141Ok(CSVFormat.EXCEL);
320 }
321
322 private void testCSV141Failure(final CSVFormat format, final int failParseRecordNo) throws IOException {
323 final Path path = Paths.get("src/test/resources/org/apache/commons/csv/CSV-141/csv-141.csv");
324 try (CSVParser parser = CSVParser.parse(path, StandardCharsets.UTF_8, format)) {
325
326 CSVRecord record = parse(parser, failParseRecordNo);
327 if (record == null) {
328 return;
329 }
330 assertEquals("1414770317901", record.get(0));
331 assertEquals("android.widget.EditText", record.get(1));
332 assertEquals("pass sem1 _84*|*", record.get(2));
333 assertEquals("0", record.get(3));
334 assertEquals("pass sem1 _8", record.get(4));
335 assertEquals(5, record.size());
336
337 record = parse(parser, failParseRecordNo);
338 if (record == null) {
339 return;
340 }
341 assertEquals("1414770318470", record.get(0));
342 assertEquals("android.widget.EditText", record.get(1));
343 assertEquals("pass sem1 _84:|", record.get(2));
344 assertEquals("0", record.get(3));
345 assertEquals("pass sem1 _84:\\", record.get(4));
346 assertEquals(5, record.size());
347
348 assertThrows(IOException.class, () -> parser.nextRecord());
349 }
350 }
351
352 private void testCSV141Ok(final CSVFormat format) throws IOException {
353 final Path path = Paths.get("src/test/resources/org/apache/commons/csv/CSV-141/csv-141.csv");
354 try (CSVParser parser = CSVParser.parse(path, StandardCharsets.UTF_8, format)) {
355
356 CSVRecord record = parser.nextRecord();
357 assertEquals("1414770317901", record.get(0));
358 assertEquals("android.widget.EditText", record.get(1));
359 assertEquals("pass sem1 _84*|*", record.get(2));
360 assertEquals("0", record.get(3));
361 assertEquals("pass sem1 _8", record.get(4));
362 assertEquals(5, record.size());
363
364 record = parser.nextRecord();
365 assertEquals("1414770318470", record.get(0));
366 assertEquals("android.widget.EditText", record.get(1));
367 assertEquals("pass sem1 _84:|", record.get(2));
368 assertEquals("0", record.get(3));
369 assertEquals("pass sem1 _84:\\", record.get(4));
370 assertEquals(5, record.size());
371
372 record = parser.nextRecord();
373 assertEquals("1414770318327", record.get(0));
374 assertEquals("android.widget.EditText", record.get(1));
375 assertEquals("pass sem1\n1414770318628\"", record.get(2));
376 assertEquals("android.widget.EditText", record.get(3));
377 assertEquals("pass sem1 _84*|*", record.get(4));
378 assertEquals("0", record.get(5));
379 assertEquals("pass sem1\n", record.get(6));
380 assertEquals(7, record.size());
381
382 record = parser.nextRecord();
383 assertNull(record);
384 }
385 }
386
387 @Test
388 public void testCSV141RFC4180() throws Exception {
389 testCSV141Failure(CSVFormat.RFC4180, 3);
390 }
391
392 @Test
393 public void testCSV235() throws IOException {
394 final String dqString = "\"aaa\",\"b\"\"bb\",\"ccc\"";
395 try (CSVParser parser = CSVFormat.RFC4180.parse(new StringReader(dqString))) {
396 final Iterator<CSVRecord> records = parser.iterator();
397 final CSVRecord record = records.next();
398 assertFalse(records.hasNext());
399 assertEquals(3, record.size());
400 assertEquals("aaa", record.get(0));
401 assertEquals("b\"bb", record.get(1));
402 assertEquals("ccc", record.get(2));
403 }
404 }
405
406 @Test
407 public void testCSV57() throws Exception {
408 try (CSVParser parser = CSVParser.parse("", CSVFormat.DEFAULT)) {
409 final List<CSVRecord> list = parser.getRecords();
410 assertNotNull(list);
411 assertEquals(0, list.size());
412 }
413 }
414
415 @Test
416 public void testDefaultFormat() throws IOException {
417
418 final String code = "" + "a,b#\n" +
419 "\"\n\",\" \",#\n" +
420 "#,\"\"\n" +
421 "# Final comment\n"
422 ;
423
424 final String[][] res = { { "a", "b#" }, { "\n", " ", "#" }, { "#", "" }, { "# Final comment" } };
425 CSVFormat format = CSVFormat.DEFAULT;
426 assertFalse(format.isCommentMarkerSet());
427 final String[][] resComments = { { "a", "b#" }, { "\n", " ", "#" } };
428 try (CSVParser parser = CSVParser.parse(code, format)) {
429 final List<CSVRecord> records = parser.getRecords();
430 assertFalse(records.isEmpty());
431 Utils.compare("Failed to parse without comments", res, records);
432 format = CSVFormat.DEFAULT.withCommentMarker('#');
433 }
434 try (CSVParser parser = CSVParser.parse(code, format)) {
435 final List<CSVRecord> records = parser.getRecords();
436 Utils.compare("Failed to parse with comments", resComments, records);
437 }
438 }
439
440 @Test
441 public void testDuplicateHeadersAllowedByDefault() throws Exception {
442 try (CSVParser parser = CSVParser.parse("a,b,a\n1,2,3\nx,y,z", CSVFormat.DEFAULT.withHeader())) {
443
444 }
445 }
446
447 @Test
448 public void testDuplicateHeadersNotAllowed() {
449 assertThrows(IllegalArgumentException.class,
450 () -> CSVParser.parse("a,b,a\n1,2,3\nx,y,z", CSVFormat.DEFAULT.withHeader().withAllowDuplicateHeaderNames(false)));
451 }
452
453 @Test
454 public void testEmptyFile() throws Exception {
455 try (CSVParser parser = CSVParser.parse(Paths.get("src/test/resources/org/apache/commons/csv/empty.txt"), StandardCharsets.UTF_8,
456 CSVFormat.DEFAULT)) {
457 assertNull(parser.nextRecord());
458 }
459 }
460
461 @Test
462 public void testEmptyFileHeaderParsing() throws Exception {
463 try (CSVParser parser = CSVParser.parse("", CSVFormat.DEFAULT.withFirstRecordAsHeader())) {
464 assertNull(parser.nextRecord());
465 assertTrue(parser.getHeaderNames().isEmpty());
466 }
467 }
468
469 @Test
470 public void testEmptyLineBehaviorCSV() throws Exception {
471 final String[] codes = { "hello,\r\n\r\n\r\n", "hello,\n\n\n", "hello,\"\"\r\n\r\n\r\n", "hello,\"\"\n\n\n" };
472 final String[][] res = { { "hello", "" }
473 };
474 for (final String code : codes) {
475 try (CSVParser parser = CSVParser.parse(code, CSVFormat.DEFAULT)) {
476 final List<CSVRecord> records = parser.getRecords();
477 assertEquals(res.length, records.size());
478 assertFalse(records.isEmpty());
479 for (int i = 0; i < res.length; i++) {
480 assertArrayEquals(res[i], records.get(i).values());
481 }
482 }
483 }
484 }
485
486 @Test
487 public void testEmptyLineBehaviorExcel() throws Exception {
488 final String[] codes = { "hello,\r\n\r\n\r\n", "hello,\n\n\n", "hello,\"\"\r\n\r\n\r\n", "hello,\"\"\n\n\n" };
489 final String[][] res = { { "hello", "" }, { "" },
490 { "" } };
491 for (final String code : codes) {
492 try (CSVParser parser = CSVParser.parse(code, CSVFormat.EXCEL)) {
493 final List<CSVRecord> records = parser.getRecords();
494 assertEquals(res.length, records.size());
495 assertFalse(records.isEmpty());
496 for (int i = 0; i < res.length; i++) {
497 assertArrayEquals(res[i], records.get(i).values());
498 }
499 }
500 }
501 }
502
503 @Test
504 public void testEmptyString() throws Exception {
505 try (CSVParser parser = CSVParser.parse("", CSVFormat.DEFAULT)) {
506 assertNull(parser.nextRecord());
507 }
508 }
509
510 @Test
511 public void testEndOfFileBehaviorCSV() throws Exception {
512 final String[] codes = { "hello,\r\n\r\nworld,\r\n", "hello,\r\n\r\nworld,", "hello,\r\n\r\nworld,\"\"\r\n", "hello,\r\n\r\nworld,\"\"",
513 "hello,\r\n\r\nworld,\n", "hello,\r\n\r\nworld,", "hello,\r\n\r\nworld,\"\"\n", "hello,\r\n\r\nworld,\"\"" };
514 final String[][] res = { { "hello", "" },
515 { "world", "" } };
516 for (final String code : codes) {
517 try (CSVParser parser = CSVParser.parse(code, CSVFormat.DEFAULT)) {
518 final List<CSVRecord> records = parser.getRecords();
519 assertEquals(res.length, records.size());
520 assertFalse(records.isEmpty());
521 for (int i = 0; i < res.length; i++) {
522 assertArrayEquals(res[i], records.get(i).values());
523 }
524 }
525 }
526 }
527
528 @Test
529 public void testEndOfFileBehaviorExcel() throws Exception {
530 final String[] codes = { "hello,\r\n\r\nworld,\r\n", "hello,\r\n\r\nworld,", "hello,\r\n\r\nworld,\"\"\r\n", "hello,\r\n\r\nworld,\"\"",
531 "hello,\r\n\r\nworld,\n", "hello,\r\n\r\nworld,", "hello,\r\n\r\nworld,\"\"\n", "hello,\r\n\r\nworld,\"\"" };
532 final String[][] res = { { "hello", "" }, { "" },
533 { "world", "" } };
534
535 for (final String code : codes) {
536 try (CSVParser parser = CSVParser.parse(code, CSVFormat.EXCEL)) {
537 final List<CSVRecord> records = parser.getRecords();
538 assertEquals(res.length, records.size());
539 assertFalse(records.isEmpty());
540 for (int i = 0; i < res.length; i++) {
541 assertArrayEquals(res[i], records.get(i).values());
542 }
543 }
544 }
545 }
546
547 @Test
548 public void testExcelFormat1() throws IOException {
549 final String code = "value1,value2,value3,value4\r\na,b,c,d\r\n x,,," + "\r\n\r\n\"\"\"hello\"\"\",\" \"\"world\"\"\",\"abc\ndef\",\r\n";
550 final String[][] res = { { "value1", "value2", "value3", "value4" }, { "a", "b", "c", "d" }, { " x", "", "", "" }, { "" },
551 { "\"hello\"", " \"world\"", "abc\ndef", "" } };
552 try (CSVParser parser = CSVParser.parse(code, CSVFormat.EXCEL)) {
553 final List<CSVRecord> records = parser.getRecords();
554 assertEquals(res.length, records.size());
555 assertFalse(records.isEmpty());
556 for (int i = 0; i < res.length; i++) {
557 assertArrayEquals(res[i], records.get(i).values());
558 }
559 }
560 }
561
562 @Test
563 public void testExcelFormat2() throws Exception {
564 final String code = "foo,baar\r\n\r\nhello,\r\n\r\nworld,\r\n";
565 final String[][] res = { { "foo", "baar" }, { "" }, { "hello", "" }, { "" }, { "world", "" } };
566 try (CSVParser parser = CSVParser.parse(code, CSVFormat.EXCEL)) {
567 final List<CSVRecord> records = parser.getRecords();
568 assertEquals(res.length, records.size());
569 assertFalse(records.isEmpty());
570 for (int i = 0; i < res.length; i++) {
571 assertArrayEquals(res[i], records.get(i).values());
572 }
573 }
574 }
575
576
577
578
579 @Test
580 public void testExcelHeaderCountLessThanData() throws Exception {
581 final String code = "A,B,C,,\r\na,b,c,d,e\r\n";
582 try (CSVParser parser = CSVParser.parse(code, EXCEL_WITH_HEADER)) {
583 parser.getRecords().forEach(record -> {
584 assertEquals("a", record.get("A"));
585 assertEquals("b", record.get("B"));
586 assertEquals("c", record.get("C"));
587 });
588 }
589 }
590
591 @Test
592 public void testFirstEndOfLineCr() throws IOException {
593 final String data = "foo\rbaar,\rhello,world\r,kanu";
594 try (CSVParser parser = CSVParser.parse(data, CSVFormat.DEFAULT)) {
595 final List<CSVRecord> records = parser.getRecords();
596 assertEquals(4, records.size());
597 assertEquals("\r", parser.getFirstEndOfLine());
598 }
599 }
600
601 @Test
602 public void testFirstEndOfLineCrLf() throws IOException {
603 final String data = "foo\r\nbaar,\r\nhello,world\r\n,kanu";
604 try (CSVParser parser = CSVParser.parse(data, CSVFormat.DEFAULT)) {
605 final List<CSVRecord> records = parser.getRecords();
606 assertEquals(4, records.size());
607 assertEquals("\r\n", parser.getFirstEndOfLine());
608 }
609 }
610
611 @Test
612 public void testFirstEndOfLineLf() throws IOException {
613 final String data = "foo\nbaar,\nhello,world\n,kanu";
614 try (CSVParser parser = CSVParser.parse(data, CSVFormat.DEFAULT)) {
615 final List<CSVRecord> records = parser.getRecords();
616 assertEquals(4, records.size());
617 assertEquals("\n", parser.getFirstEndOfLine());
618 }
619 }
620
621 @Test
622 public void testForEach() throws Exception {
623 try (Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z");
624 CSVParser parser = CSVFormat.DEFAULT.parse(in)) {
625 final List<CSVRecord> records = new ArrayList<>();
626 for (final CSVRecord record : parser) {
627 records.add(record);
628 }
629 assertEquals(3, records.size());
630 assertArrayEquals(new String[] { "a", "b", "c" }, records.get(0).values());
631 assertArrayEquals(new String[] { "1", "2", "3" }, records.get(1).values());
632 assertArrayEquals(new String[] { "x", "y", "z" }, records.get(2).values());
633 }
634 }
635
636 @Test
637 public void testGetHeaderComment_HeaderComment1() throws IOException {
638 try (CSVParser parser = CSVParser.parse(CSV_INPUT_HEADER_COMMENT, FORMAT_AUTO_HEADER)) {
639 parser.getRecords();
640
641 assertTrue(parser.hasHeaderComment());
642 assertEquals("header comment", parser.getHeaderComment());
643 }
644 }
645
646 @Test
647 public void testGetHeaderComment_HeaderComment2() throws IOException {
648 try (CSVParser parser = CSVParser.parse(CSV_INPUT_HEADER_COMMENT, FORMAT_EXPLICIT_HEADER)) {
649 parser.getRecords();
650
651 assertTrue(parser.hasHeaderComment());
652 assertEquals("header comment", parser.getHeaderComment());
653 }
654 }
655
656 @Test
657 public void testGetHeaderComment_HeaderComment3() throws IOException {
658 try (CSVParser parser = CSVParser.parse(CSV_INPUT_HEADER_COMMENT, FORMAT_EXPLICIT_HEADER_NOSKIP)) {
659 parser.getRecords();
660
661 assertFalse(parser.hasHeaderComment());
662 assertNull(parser.getHeaderComment());
663 }
664 }
665
666 @Test
667 public void testGetHeaderComment_HeaderTrailerComment() throws IOException {
668 try (CSVParser parser = CSVParser.parse(CSV_INPUT_MULTILINE_HEADER_TRAILER_COMMENT, FORMAT_AUTO_HEADER)) {
669 parser.getRecords();
670
671 assertTrue(parser.hasHeaderComment());
672 assertEquals("multi-line" + LF + "header comment", parser.getHeaderComment());
673 }
674 }
675
676 @Test
677 public void testGetHeaderComment_NoComment1() throws IOException {
678 try (CSVParser parser = CSVParser.parse(CSV_INPUT_NO_COMMENT, FORMAT_AUTO_HEADER)) {
679 parser.getRecords();
680
681 assertFalse(parser.hasHeaderComment());
682 assertNull(parser.getHeaderComment());
683 }
684 }
685
686 @Test
687 public void testGetHeaderComment_NoComment2() throws IOException {
688 try (CSVParser parser = CSVParser.parse(CSV_INPUT_NO_COMMENT, FORMAT_EXPLICIT_HEADER)) {
689 parser.getRecords();
690
691 assertFalse(parser.hasHeaderComment());
692 assertNull(parser.getHeaderComment());
693 }
694 }
695
696 @Test
697 public void testGetHeaderComment_NoComment3() throws IOException {
698 try (CSVParser parser = CSVParser.parse(CSV_INPUT_NO_COMMENT, FORMAT_EXPLICIT_HEADER_NOSKIP)) {
699 parser.getRecords();
700
701 assertFalse(parser.hasHeaderComment());
702 assertNull(parser.getHeaderComment());
703 }
704 }
705
706 @Test
707 public void testGetHeaderMap() throws Exception {
708 try (CSVParser parser = CSVParser.parse("a,b,c\n1,2,3\nx,y,z", CSVFormat.DEFAULT.withHeader("A", "B", "C"))) {
709 final Map<String, Integer> headerMap = parser.getHeaderMap();
710 final Iterator<String> columnNames = headerMap.keySet().iterator();
711
712 assertEquals("A", columnNames.next());
713 assertEquals("B", columnNames.next());
714 assertEquals("C", columnNames.next());
715 final Iterator<CSVRecord> records = parser.iterator();
716
717
718 for (int i = 0; i < 3; i++) {
719 assertTrue(records.hasNext());
720 final CSVRecord record = records.next();
721 assertEquals(record.get(0), record.get("A"));
722 assertEquals(record.get(1), record.get("B"));
723 assertEquals(record.get(2), record.get("C"));
724 }
725
726 assertFalse(records.hasNext());
727 }
728 }
729
730 @Test
731 public void testGetHeaderNames() throws IOException {
732 try (CSVParser parser = CSVParser.parse("a,b,c\n1,2,3\nx,y,z", CSVFormat.DEFAULT.withHeader("A", "B", "C"))) {
733 final Map<String, Integer> nameIndexMap = parser.getHeaderMap();
734 final List<String> headerNames = parser.getHeaderNames();
735 assertNotNull(headerNames);
736 assertEquals(nameIndexMap.size(), headerNames.size());
737 for (int i = 0; i < headerNames.size(); i++) {
738 final String name = headerNames.get(i);
739 assertEquals(i, nameIndexMap.get(name).intValue());
740 }
741 }
742 }
743
744 @Test
745 public void testGetHeaderNamesReadOnly() throws IOException {
746 try (CSVParser parser = CSVParser.parse("a,b,c\n1,2,3\nx,y,z", CSVFormat.DEFAULT.withHeader("A", "B", "C"))) {
747 final List<String> headerNames = parser.getHeaderNames();
748 assertNotNull(headerNames);
749 assertThrows(UnsupportedOperationException.class, () -> headerNames.add("This is a read-only list."));
750 }
751 }
752
753 @Test
754 public void testGetLine() throws IOException {
755 try (CSVParser parser = CSVParser.parse(CSV_INPUT, CSVFormat.DEFAULT.withIgnoreSurroundingSpaces())) {
756 for (final String[] re : RESULT) {
757 assertArrayEquals(re, parser.nextRecord().values());
758 }
759
760 assertNull(parser.nextRecord());
761 }
762 }
763
764 @Test
765 public void testGetLineNumberWithCR() throws Exception {
766 validateLineNumbers(String.valueOf(CR));
767 }
768
769 @Test
770 public void testGetLineNumberWithCRLF() throws Exception {
771 validateLineNumbers(CRLF);
772 }
773
774 @Test
775 public void testGetLineNumberWithLF() throws Exception {
776 validateLineNumbers(String.valueOf(LF));
777 }
778
779 @Test
780 public void testGetOneLine() throws IOException {
781 try (CSVParser parser = CSVParser.parse(CSV_INPUT_1, CSVFormat.DEFAULT)) {
782 final CSVRecord record = parser.getRecords().get(0);
783 assertArrayEquals(RESULT[0], record.values());
784 }
785 }
786
787
788
789
790
791
792 @Test
793 public void testGetOneLineOneParser() throws IOException {
794 final CSVFormat format = CSVFormat.DEFAULT;
795 try (PipedWriter writer = new PipedWriter();
796 CSVParser parser = CSVParser.builder()
797 .setReader(new PipedReader(writer))
798 .setFormat(format)
799 .get()) {
800 writer.append(CSV_INPUT_1);
801 writer.append(format.getRecordSeparator());
802 final CSVRecord record1 = parser.nextRecord();
803 assertArrayEquals(RESULT[0], record1.values());
804 writer.append(CSV_INPUT_2);
805 writer.append(format.getRecordSeparator());
806 final CSVRecord record2 = parser.nextRecord();
807 assertArrayEquals(RESULT[1], record2.values());
808 }
809 }
810
811 @Test
812 public void testGetRecordFourBytesRead() throws Exception {
813 final String code = "id,a,b,c\n" +
814 "1,😊,🤔,😂\n" +
815 "2,😊,🤔,😂\n" +
816 "3,😊,🤔,😂\n";
817 final CSVFormat format = CSVFormat.Builder.create()
818 .setDelimiter(',')
819 .setQuote('\'')
820 .get();
821 try (CSVParser parser = CSVParser.builder().setReader(new StringReader(code)).setFormat(format).setCharset(UTF_8).setTrackBytes(true).get()) {
822 CSVRecord record = new CSVRecord(parser, null, null, 1L, 0L, 0L);
823
824 assertEquals(0, parser.getRecordNumber());
825 assertNotNull(record = parser.nextRecord());
826 assertEquals(1, record.getRecordNumber());
827 assertEquals(code.indexOf('i'), record.getCharacterPosition());
828 assertEquals(record.getBytePosition(), record.getCharacterPosition());
829
830 assertNotNull(record = parser.nextRecord());
831 assertEquals(2, record.getRecordNumber());
832 assertEquals(code.indexOf('1'), record.getCharacterPosition());
833 assertEquals(record.getBytePosition(), record.getCharacterPosition());
834 assertNotNull(record = parser.nextRecord());
835 assertEquals(3, record.getRecordNumber());
836 assertEquals(code.indexOf('2'), record.getCharacterPosition());
837 assertEquals(record.getBytePosition(), 26);
838 assertNotNull(record = parser.nextRecord());
839 assertEquals(4, record.getRecordNumber());
840 assertEquals(code.indexOf('3'), record.getCharacterPosition());
841 assertEquals(record.getBytePosition(), 43);
842 }
843 }
844
845 @Test
846 public void testGetRecordNumberWithCR() throws Exception {
847 validateRecordNumbers(String.valueOf(CR));
848 }
849
850 @Test
851 public void testGetRecordNumberWithCRLF() throws Exception {
852 validateRecordNumbers(CRLF);
853 }
854
855 @Test
856 public void testGetRecordNumberWithLF() throws Exception {
857 validateRecordNumbers(String.valueOf(LF));
858 }
859
860 @Test
861 public void testGetRecordPositionWithCRLF() throws Exception {
862 validateRecordPosition(CRLF);
863 }
864
865 @Test
866 public void testGetRecordPositionWithLF() throws Exception {
867 validateRecordPosition(String.valueOf(LF));
868 }
869
870 @Test
871 public void testGetRecords() throws IOException {
872 try (CSVParser parser = CSVParser.parse(CSV_INPUT, CSVFormat.DEFAULT.withIgnoreSurroundingSpaces())) {
873 final List<CSVRecord> records = parser.getRecords();
874 assertEquals(RESULT.length, records.size());
875 assertFalse(records.isEmpty());
876 for (int i = 0; i < RESULT.length; i++) {
877 assertArrayEquals(RESULT[i], records.get(i).values());
878 }
879 }
880 }
881
882 @Test
883 public void testGetRecordsFromBrokenInputStream() throws IOException {
884 @SuppressWarnings("resource")
885 final CSVParser parser = CSVParser.parse(new BrokenInputStream(), UTF_8, CSVFormat.DEFAULT);
886 assertThrows(UncheckedIOException.class, parser::getRecords);
887
888 }
889
890 @Test
891 public void testGetRecordThreeBytesRead() throws Exception {
892 final String code = "id,date,val5,val4\n" +
893 "11111111111111,'4017-09-01',きちんと節分近くには咲いてる~,v4\n" +
894 "22222222222222,'4017-01-01',おはよう私の友人~,v4\n" +
895 "33333333333333,'4017-01-01',きる自然の力ってすごいな~,v4\n";
896 final CSVFormat format = CSVFormat.Builder.create()
897 .setDelimiter(',')
898 .setQuote('\'')
899 .get();
900 try (CSVParser parser = CSVParser.builder().setReader(new StringReader(code)).setFormat(format).setCharset(UTF_8).setTrackBytes(true).get()) {
901 CSVRecord record = new CSVRecord(parser, null, null, 1L, 0L, 0L);
902
903 assertEquals(0, parser.getRecordNumber());
904 assertNotNull(record = parser.nextRecord());
905 assertEquals(1, record.getRecordNumber());
906 assertEquals(code.indexOf('i'), record.getCharacterPosition());
907 assertEquals(record.getBytePosition(), record.getCharacterPosition());
908
909 assertNotNull(record = parser.nextRecord());
910 assertEquals(2, record.getRecordNumber());
911 assertEquals(code.indexOf('1'), record.getCharacterPosition());
912 assertEquals(record.getBytePosition(), record.getCharacterPosition());
913
914 assertNotNull(record = parser.nextRecord());
915 assertEquals(3, record.getRecordNumber());
916 assertEquals(code.indexOf('2'), record.getCharacterPosition());
917 assertEquals(record.getBytePosition(), 95);
918
919 assertNotNull(record = parser.nextRecord());
920 assertEquals(4, record.getRecordNumber());
921 assertEquals(code.indexOf('3'), record.getCharacterPosition());
922 assertEquals(record.getBytePosition(), 154);
923 }
924 }
925
926 @Test
927 public void testGetRecordWithMultiLineValues() throws Exception {
928 try (CSVParser parser = CSVParser.parse("\"a\r\n1\",\"a\r\n2\"" + CRLF + "\"b\r\n1\",\"b\r\n2\"" + CRLF + "\"c\r\n1\",\"c\r\n2\"",
929 CSVFormat.DEFAULT.withRecordSeparator(CRLF))) {
930 CSVRecord record;
931 assertEquals(0, parser.getRecordNumber());
932 assertEquals(0, parser.getCurrentLineNumber());
933 assertNotNull(record = parser.nextRecord());
934 assertEquals(3, parser.getCurrentLineNumber());
935 assertEquals(1, record.getRecordNumber());
936 assertEquals(1, parser.getRecordNumber());
937 assertNotNull(record = parser.nextRecord());
938 assertEquals(6, parser.getCurrentLineNumber());
939 assertEquals(2, record.getRecordNumber());
940 assertEquals(2, parser.getRecordNumber());
941 assertNotNull(record = parser.nextRecord());
942 assertEquals(9, parser.getCurrentLineNumber());
943 assertEquals(3, record.getRecordNumber());
944 assertEquals(3, parser.getRecordNumber());
945 assertNull(record = parser.nextRecord());
946 assertEquals(9, parser.getCurrentLineNumber());
947 assertEquals(3, parser.getRecordNumber());
948 }
949 }
950
951 @Test
952 public void testGetTrailerComment_HeaderComment1() throws IOException {
953 try (CSVParser parser = CSVParser.parse(CSV_INPUT_HEADER_COMMENT, FORMAT_AUTO_HEADER)) {
954 parser.getRecords();
955 assertFalse(parser.hasTrailerComment());
956 assertNull(parser.getTrailerComment());
957 }
958 }
959
960 @Test
961 public void testGetTrailerComment_HeaderComment2() throws IOException {
962 try (CSVParser parser = CSVParser.parse(CSV_INPUT_HEADER_COMMENT, FORMAT_EXPLICIT_HEADER)) {
963 parser.getRecords();
964 assertFalse(parser.hasTrailerComment());
965 assertNull(parser.getTrailerComment());
966 }
967 }
968
969 @Test
970 public void testGetTrailerComment_HeaderComment3() throws IOException {
971 try (CSVParser parser = CSVParser.parse(CSV_INPUT_HEADER_COMMENT, FORMAT_EXPLICIT_HEADER_NOSKIP)) {
972 parser.getRecords();
973 assertFalse(parser.hasTrailerComment());
974 assertNull(parser.getTrailerComment());
975 }
976 }
977
978 @Test
979 public void testGetTrailerComment_HeaderTrailerComment1() throws IOException {
980 try (CSVParser parser = CSVParser.parse(CSV_INPUT_HEADER_TRAILER_COMMENT, FORMAT_AUTO_HEADER)) {
981 parser.getRecords();
982 assertTrue(parser.hasTrailerComment());
983 assertEquals("comment", parser.getTrailerComment());
984 }
985 }
986
987 @Test
988 public void testGetTrailerComment_HeaderTrailerComment2() throws IOException {
989 try (CSVParser parser = CSVParser.parse(CSV_INPUT_HEADER_TRAILER_COMMENT, FORMAT_EXPLICIT_HEADER)) {
990 parser.getRecords();
991 assertTrue(parser.hasTrailerComment());
992 assertEquals("comment", parser.getTrailerComment());
993 }
994 }
995
996 @Test
997 public void testGetTrailerComment_HeaderTrailerComment3() throws IOException {
998 try (CSVParser parser = CSVParser.parse(CSV_INPUT_HEADER_TRAILER_COMMENT, FORMAT_EXPLICIT_HEADER_NOSKIP)) {
999 parser.getRecords();
1000 assertTrue(parser.hasTrailerComment());
1001 assertEquals("comment", parser.getTrailerComment());
1002 }
1003 }
1004
1005 @Test
1006 public void testGetTrailerComment_MultilineComment() throws IOException {
1007 try (CSVParser parser = CSVParser.parse(CSV_INPUT_MULTILINE_HEADER_TRAILER_COMMENT, FORMAT_AUTO_HEADER)) {
1008 parser.getRecords();
1009 assertTrue(parser.hasTrailerComment());
1010 assertEquals("multi-line" + LF + "comment", parser.getTrailerComment());
1011 }
1012 }
1013
1014 @Test
1015 public void testHeader() throws Exception {
1016 final Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z");
1017
1018 try (CSVParser parser = CSVFormat.DEFAULT.withHeader().parse(in)) {
1019 final Iterator<CSVRecord> records = parser.iterator();
1020
1021 for (int i = 0; i < 2; i++) {
1022 assertTrue(records.hasNext());
1023 final CSVRecord record = records.next();
1024 assertEquals(record.get(0), record.get("a"));
1025 assertEquals(record.get(1), record.get("b"));
1026 assertEquals(record.get(2), record.get("c"));
1027 }
1028
1029 assertFalse(records.hasNext());
1030 }
1031 }
1032
1033 @Test
1034 public void testHeaderComment() throws Exception {
1035 final Reader in = new StringReader("# comment\na,b,c\n1,2,3\nx,y,z");
1036 try (CSVParser parser = CSVFormat.DEFAULT.withCommentMarker('#').withHeader().parse(in)) {
1037 final Iterator<CSVRecord> records = parser.iterator();
1038 for (int i = 0; i < 2; i++) {
1039 assertTrue(records.hasNext());
1040 final CSVRecord record = records.next();
1041 assertEquals(record.get(0), record.get("a"));
1042 assertEquals(record.get(1), record.get("b"));
1043 assertEquals(record.get(2), record.get("c"));
1044 }
1045 assertFalse(records.hasNext());
1046 }
1047 }
1048
1049 @Test
1050 public void testHeaderMissing() throws Exception {
1051 final Reader in = new StringReader("a,,c\n1,2,3\nx,y,z");
1052 try (CSVParser parser = CSVFormat.DEFAULT.withHeader().withAllowMissingColumnNames().parse(in)) {
1053 final Iterator<CSVRecord> records = parser.iterator();
1054 for (int i = 0; i < 2; i++) {
1055 assertTrue(records.hasNext());
1056 final CSVRecord record = records.next();
1057 assertEquals(record.get(0), record.get("a"));
1058 assertEquals(record.get(2), record.get("c"));
1059 }
1060 assertFalse(records.hasNext());
1061 }
1062 }
1063
1064 @Test
1065 public void testHeaderMissingWithNull() throws Exception {
1066 final Reader in = new StringReader("a,,c,,e\n1,2,3,4,5\nv,w,x,y,z");
1067 try (CSVParser parser = CSVFormat.DEFAULT.withHeader().withNullString("").withAllowMissingColumnNames().parse(in)) {
1068 parser.iterator();
1069 }
1070 }
1071
1072 @Test
1073 public void testHeadersMissing() throws Exception {
1074 try (Reader in = new StringReader("a,,c,,e\n1,2,3,4,5\nv,w,x,y,z");
1075 CSVParser parser = CSVFormat.DEFAULT.withHeader().withAllowMissingColumnNames().parse(in)) {
1076 parser.iterator();
1077 }
1078 }
1079
1080 @Test
1081 public void testHeadersMissingException() {
1082 final Reader in = new StringReader("a,,c,,e\n1,2,3,4,5\nv,w,x,y,z");
1083 assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withHeader().parse(in).iterator());
1084 }
1085
1086 @Test
1087 public void testHeadersMissingOneColumnException() {
1088 final Reader in = new StringReader("a,,c,d,e\n1,2,3,4,5\nv,w,x,y,z");
1089 assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withHeader().parse(in).iterator());
1090 }
1091
1092 @Test
1093 public void testHeadersWithNullColumnName() throws IOException {
1094 final Reader in = new StringReader("header1,null,header3\n1,2,3\n4,5,6");
1095 try (CSVParser parser = CSVFormat.DEFAULT.withHeader().withNullString("null").withAllowMissingColumnNames().parse(in)) {
1096 final Iterator<CSVRecord> records = parser.iterator();
1097 final CSVRecord record = records.next();
1098
1099 @SuppressWarnings("resource")
1100 final CSVParser recordParser = record.getParser();
1101 assertEquals(Arrays.asList("header1", "header3"), recordParser.getHeaderNames());
1102 assertEquals(2, recordParser.getHeaderMap().size());
1103 }
1104 }
1105
1106 @Test
1107 public void testIgnoreCaseHeaderMapping() throws Exception {
1108 final Reader reader = new StringReader("1,2,3");
1109 try (CSVParser parser = CSVFormat.DEFAULT.withHeader("One", "TWO", "three").withIgnoreHeaderCase().parse(reader)) {
1110 final Iterator<CSVRecord> records = parser.iterator();
1111 final CSVRecord record = records.next();
1112 assertEquals("1", record.get("one"));
1113 assertEquals("2", record.get("two"));
1114 assertEquals("3", record.get("THREE"));
1115 }
1116 }
1117
1118 @Test
1119 public void testIgnoreEmptyLines() throws IOException {
1120 final String code = "\nfoo,baar\n\r\n,\n\n,world\r\n\n";
1121
1122
1123 try (CSVParser parser = CSVParser.parse(code, CSVFormat.DEFAULT)) {
1124 final List<CSVRecord> records = parser.getRecords();
1125 assertEquals(3, records.size());
1126 }
1127 }
1128
1129 @Test
1130 public void testInvalidFormat() {
1131 assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withDelimiter(CR));
1132 }
1133
1134 @Test
1135 public void testIterator() throws Exception {
1136 final Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z");
1137 try (CSVParser parser = CSVFormat.DEFAULT.parse(in)) {
1138 final Iterator<CSVRecord> iterator = parser.iterator();
1139 assertTrue(iterator.hasNext());
1140 assertThrows(UnsupportedOperationException.class, iterator::remove);
1141 assertArrayEquals(new String[] { "a", "b", "c" }, iterator.next().values());
1142 assertArrayEquals(new String[] { "1", "2", "3" }, iterator.next().values());
1143 assertTrue(iterator.hasNext());
1144 assertTrue(iterator.hasNext());
1145 assertTrue(iterator.hasNext());
1146 assertArrayEquals(new String[] { "x", "y", "z" }, iterator.next().values());
1147 assertFalse(iterator.hasNext());
1148 assertThrows(NoSuchElementException.class, iterator::next);
1149 }
1150 }
1151
1152 @Test
1153 public void testIteratorSequenceBreaking() throws IOException {
1154 final String fiveRows = "1\n2\n3\n4\n5\n";
1155
1156 try (CSVParser parser = CSVFormat.DEFAULT.parse(new StringReader(fiveRows))) {
1157 final Iterator<CSVRecord> iter = parser.iterator();
1158 int recordNumber = 0;
1159 while (iter.hasNext()) {
1160 final CSVRecord record = iter.next();
1161 recordNumber++;
1162 assertEquals(String.valueOf(recordNumber), record.get(0));
1163 if (recordNumber >= 2) {
1164 break;
1165 }
1166 }
1167 iter.hasNext();
1168 while (iter.hasNext()) {
1169 final CSVRecord record = iter.next();
1170 recordNumber++;
1171 assertEquals(String.valueOf(recordNumber), record.get(0));
1172 }
1173 }
1174
1175 try (CSVParser parser = CSVFormat.DEFAULT.parse(new StringReader(fiveRows))) {
1176 int recordNumber = 0;
1177 for (final CSVRecord record : parser) {
1178 recordNumber++;
1179 assertEquals(String.valueOf(recordNumber), record.get(0));
1180 if (recordNumber >= 2) {
1181 break;
1182 }
1183 }
1184 for (final CSVRecord record : parser) {
1185 recordNumber++;
1186 assertEquals(String.valueOf(recordNumber), record.get(0));
1187 }
1188 }
1189
1190 try (CSVParser parser = CSVFormat.DEFAULT.parse(new StringReader(fiveRows))) {
1191 int recordNumber = 0;
1192 for (final CSVRecord record : parser) {
1193 recordNumber++;
1194 assertEquals(String.valueOf(recordNumber), record.get(0));
1195 if (recordNumber >= 2) {
1196 break;
1197 }
1198 }
1199 parser.iterator().hasNext();
1200 for (final CSVRecord record : parser) {
1201 recordNumber++;
1202 assertEquals(String.valueOf(recordNumber), record.get(0));
1203 }
1204 }
1205 }
1206
1207 @Test
1208 public void testLineFeedEndings() throws IOException {
1209 final String code = "foo\nbaar,\nhello,world\n,kanu";
1210 try (CSVParser parser = CSVParser.parse(code, CSVFormat.DEFAULT)) {
1211 final List<CSVRecord> records = parser.getRecords();
1212 assertEquals(4, records.size());
1213 }
1214 }
1215
1216 @Test
1217 public void testMappedButNotSetAsOutlook2007ContactExport() throws Exception {
1218 final Reader in = new StringReader("a,b,c\n1,2\nx,y,z");
1219 try (CSVParser parser = CSVFormat.DEFAULT.withHeader("A", "B", "C").withSkipHeaderRecord().parse(in)) {
1220 final Iterator<CSVRecord> records = parser.iterator();
1221 CSVRecord record;
1222
1223 record = records.next();
1224 assertTrue(record.isMapped("A"));
1225 assertTrue(record.isMapped("B"));
1226 assertTrue(record.isMapped("C"));
1227 assertTrue(record.isSet("A"));
1228 assertTrue(record.isSet("B"));
1229 assertFalse(record.isSet("C"));
1230 assertEquals("1", record.get("A"));
1231 assertEquals("2", record.get("B"));
1232 assertFalse(record.isConsistent());
1233
1234 record = records.next();
1235 assertTrue(record.isMapped("A"));
1236 assertTrue(record.isMapped("B"));
1237 assertTrue(record.isMapped("C"));
1238 assertTrue(record.isSet("A"));
1239 assertTrue(record.isSet("B"));
1240 assertTrue(record.isSet("C"));
1241 assertEquals("x", record.get("A"));
1242 assertEquals("y", record.get("B"));
1243 assertEquals("z", record.get("C"));
1244 assertTrue(record.isConsistent());
1245
1246 assertFalse(records.hasNext());
1247 }
1248 }
1249
1250 @Test
1251 @Disabled
1252 public void testMongoDbCsv() throws Exception {
1253 try (CSVParser parser = CSVParser.parse("\"a a\",b,c" + LF + "d,e,f", CSVFormat.MONGODB_CSV)) {
1254 final Iterator<CSVRecord> itr1 = parser.iterator();
1255 final Iterator<CSVRecord> itr2 = parser.iterator();
1256
1257 final CSVRecord first = itr1.next();
1258 assertEquals("a a", first.get(0));
1259 assertEquals("b", first.get(1));
1260 assertEquals("c", first.get(2));
1261
1262 final CSVRecord second = itr2.next();
1263 assertEquals("d", second.get(0));
1264 assertEquals("e", second.get(1));
1265 assertEquals("f", second.get(2));
1266 }
1267 }
1268
1269 @Test
1270
1271 public void testMultipleIterators() throws Exception {
1272 try (CSVParser parser = CSVParser.parse("a,b,c" + CRLF + "d,e,f", CSVFormat.DEFAULT)) {
1273 final Iterator<CSVRecord> itr1 = parser.iterator();
1274
1275 final CSVRecord first = itr1.next();
1276 assertEquals("a", first.get(0));
1277 assertEquals("b", first.get(1));
1278 assertEquals("c", first.get(2));
1279
1280 final CSVRecord second = itr1.next();
1281 assertEquals("d", second.get(0));
1282 assertEquals("e", second.get(1));
1283 assertEquals("f", second.get(2));
1284 }
1285 }
1286
1287 @Test
1288 public void testNewCSVParserNullReaderFormat() {
1289 assertThrows(NullPointerException.class, () -> new CSVParser(null, CSVFormat.DEFAULT));
1290 }
1291
1292 @Test
1293 public void testNewCSVParserReaderNullFormat() {
1294 assertThrows(NullPointerException.class, () -> new CSVParser(new StringReader(""), null));
1295 }
1296
1297 @Test
1298 public void testNoHeaderMap() throws Exception {
1299 try (CSVParser parser = CSVParser.parse("a,b,c\n1,2,3\nx,y,z", CSVFormat.DEFAULT)) {
1300 assertNull(parser.getHeaderMap());
1301 }
1302 }
1303
1304 @Test
1305 public void testNotValueCSV() throws IOException {
1306 final String source = "#";
1307 final CSVFormat csvFormat = CSVFormat.DEFAULT.withCommentMarker('#');
1308 try (CSVParser csvParser = csvFormat.parse(new StringReader(source))) {
1309 final CSVRecord csvRecord = csvParser.nextRecord();
1310 assertNull(csvRecord);
1311 }
1312 }
1313
1314 @Test
1315 public void testParse() throws Exception {
1316 final ClassLoader loader = ClassLoader.getSystemClassLoader();
1317 final URL url = loader.getResource("org/apache/commons/csv/CSVFileParser/test.csv");
1318 final CSVFormat format = CSVFormat.DEFAULT.builder().setHeader("A", "B", "C", "D").get();
1319 final Charset charset = StandardCharsets.UTF_8;
1320
1321 try (CSVParser parser = CSVParser.parse(new InputStreamReader(url.openStream(), charset), format)) {
1322 parseFully(parser);
1323 }
1324 try (CSVParser parser = CSVParser.builder().setReader(new InputStreamReader(url.openStream(), charset)).setFormat(format).get()) {
1325 parseFully(parser);
1326 }
1327
1328 final Path path = Paths.get(url.toURI());
1329 final String string = new String(Files.readAllBytes(path), charset);
1330 try (CSVParser parser = CSVParser.parse(string, format)) {
1331 parseFully(parser);
1332 }
1333 try (CSVParser parser = CSVParser.builder().setCharSequence(string).setFormat(format).get()) {
1334 parseFully(parser);
1335 }
1336
1337 final File file = new File(url.toURI());
1338 try (CSVParser parser = CSVParser.parse(file, charset, format)) {
1339 parseFully(parser);
1340 }
1341 try (CSVParser parser = CSVParser.builder().setFile(file).setCharset(charset).setFormat(format).get()) {
1342 parseFully(parser);
1343 }
1344
1345 try (CSVParser parser = CSVParser.parse(url.openStream(), charset, format)) {
1346 parseFully(parser);
1347 }
1348 try (CSVParser parser = CSVParser.builder().setInputStream(url.openStream()).setCharset(charset).setFormat(format).get()) {
1349 parseFully(parser);
1350 }
1351
1352 try (CSVParser parser = CSVParser.parse(path, charset, format)) {
1353 parseFully(parser);
1354 }
1355 try (CSVParser parser = CSVParser.builder().setPath(path).setCharset(charset).setFormat(format).get()) {
1356 parseFully(parser);
1357 }
1358
1359 try (CSVParser parser = CSVParser.parse(url, charset, format)) {
1360 parseFully(parser);
1361 }
1362 try (CSVParser parser = CSVParser.builder().setURI(url.toURI()).setCharset(charset).setFormat(format).get()) {
1363 parseFully(parser);
1364 }
1365
1366 try (CSVParser parser = new CSVParser(new InputStreamReader(url.openStream(), charset), format)) {
1367 parseFully(parser);
1368 }
1369 try (CSVParser parser = CSVParser.builder().setReader(new InputStreamReader(url.openStream(), charset)).setFormat(format).get()) {
1370 parseFully(parser);
1371 }
1372
1373 try (CSVParser parser = new CSVParser(new InputStreamReader(url.openStream(), charset), format, 0, 1)) {
1374 parseFully(parser);
1375 }
1376 try (CSVParser parser = CSVParser.builder().setReader(new InputStreamReader(url.openStream(), charset)).setFormat(format).setCharacterOffset(0)
1377 .setRecordNumber(0).get()) {
1378 parseFully(parser);
1379 }
1380 }
1381
1382 @Test
1383 public void testParseFileNullFormat() {
1384 assertThrows(NullPointerException.class, () -> CSVParser.parse(new File("CSVFileParser/test.csv"), Charset.defaultCharset(), null));
1385 }
1386
1387 @Test
1388 public void testParseNullFileFormat() {
1389 assertThrows(NullPointerException.class, () -> CSVParser.parse((File) null, Charset.defaultCharset(), CSVFormat.DEFAULT));
1390 }
1391
1392 @Test
1393 public void testParseNullPathFormat() {
1394 assertThrows(NullPointerException.class, () -> CSVParser.parse((Path) null, Charset.defaultCharset(), CSVFormat.DEFAULT));
1395 }
1396
1397 @Test
1398 public void testParseNullStringFormat() {
1399 assertThrows(NullPointerException.class, () -> CSVParser.parse((String) null, CSVFormat.DEFAULT));
1400 }
1401
1402 @Test
1403 public void testParseNullUrlCharsetFormat() {
1404 assertThrows(NullPointerException.class, () -> CSVParser.parse((URL) null, Charset.defaultCharset(), CSVFormat.DEFAULT));
1405 }
1406
1407 @Test
1408 public void testParserUrlNullCharsetFormat() {
1409 assertThrows(NullPointerException.class, () -> CSVParser.parse(new URL("https://commons.apache.org"), null, CSVFormat.DEFAULT));
1410 }
1411
1412 @Test
1413 public void testParseStringNullFormat() {
1414 assertThrows(NullPointerException.class, () -> CSVParser.parse("csv data", (CSVFormat) null));
1415 }
1416
1417 @Test
1418 public void testParseUrlCharsetNullFormat() {
1419 assertThrows(NullPointerException.class, () -> CSVParser.parse(new URL("https://commons.apache.org"), Charset.defaultCharset(), null));
1420 }
1421
1422 @Test
1423 public void testParseWithDelimiterStringWithEscape() throws IOException {
1424 final String source = "a![!|!]b![|]c[|]xyz\r\nabc[abc][|]xyz";
1425 final CSVFormat csvFormat = CSVFormat.DEFAULT.builder().setDelimiter("[|]").setEscape('!').get();
1426 try (CSVParser csvParser = csvFormat.parse(new StringReader(source))) {
1427 CSVRecord csvRecord = csvParser.nextRecord();
1428 assertEquals("a[|]b![|]c", csvRecord.get(0));
1429 assertEquals("xyz", csvRecord.get(1));
1430 csvRecord = csvParser.nextRecord();
1431 assertEquals("abc[abc]", csvRecord.get(0));
1432 assertEquals("xyz", csvRecord.get(1));
1433 }
1434 }
1435
1436 @Test
1437 public void testParseWithDelimiterStringWithQuote() throws IOException {
1438 final String source = "'a[|]b[|]c'[|]xyz\r\nabc[abc][|]xyz";
1439 final CSVFormat csvFormat = CSVFormat.DEFAULT.builder().setDelimiter("[|]").setQuote('\'').get();
1440 try (CSVParser csvParser = csvFormat.parse(new StringReader(source))) {
1441 CSVRecord csvRecord = csvParser.nextRecord();
1442 assertEquals("a[|]b[|]c", csvRecord.get(0));
1443 assertEquals("xyz", csvRecord.get(1));
1444 csvRecord = csvParser.nextRecord();
1445 assertEquals("abc[abc]", csvRecord.get(0));
1446 assertEquals("xyz", csvRecord.get(1));
1447 }
1448 }
1449
1450 @Test
1451 public void testParseWithDelimiterWithEscape() throws IOException {
1452 final String source = "a!,b!,c,xyz";
1453 final CSVFormat csvFormat = CSVFormat.DEFAULT.withEscape('!');
1454 try (CSVParser csvParser = csvFormat.parse(new StringReader(source))) {
1455 final CSVRecord csvRecord = csvParser.nextRecord();
1456 assertEquals("a,b,c", csvRecord.get(0));
1457 assertEquals("xyz", csvRecord.get(1));
1458 }
1459 }
1460
1461 @Test
1462 public void testParseWithDelimiterWithQuote() throws IOException {
1463 final String source = "'a,b,c',xyz";
1464 final CSVFormat csvFormat = CSVFormat.DEFAULT.withQuote('\'');
1465 try (CSVParser csvParser = csvFormat.parse(new StringReader(source))) {
1466 final CSVRecord csvRecord = csvParser.nextRecord();
1467 assertEquals("a,b,c", csvRecord.get(0));
1468 assertEquals("xyz", csvRecord.get(1));
1469 }
1470 }
1471
1472 @Test
1473 public void testParseWithQuoteThrowsException() {
1474 final CSVFormat csvFormat = CSVFormat.DEFAULT.withQuote('\'');
1475 assertThrows(IOException.class, () -> csvFormat.parse(new StringReader("'a,b,c','")).nextRecord());
1476 assertThrows(IOException.class, () -> csvFormat.parse(new StringReader("'a,b,c'abc,xyz")).nextRecord());
1477 assertThrows(IOException.class, () -> csvFormat.parse(new StringReader("'abc'a,b,c',xyz")).nextRecord());
1478 }
1479
1480 @Test
1481 public void testParseWithQuoteWithEscape() throws IOException {
1482 final String source = "'a?,b?,c?d',xyz";
1483 final CSVFormat csvFormat = CSVFormat.DEFAULT.withQuote('\'').withEscape('?');
1484 try (CSVParser csvParser = csvFormat.parse(new StringReader(source))) {
1485 final CSVRecord csvRecord = csvParser.nextRecord();
1486 assertEquals("a,b,c?d", csvRecord.get(0));
1487 assertEquals("xyz", csvRecord.get(1));
1488 }
1489 }
1490
1491 @ParameterizedTest
1492 @EnumSource(CSVFormat.Predefined.class)
1493 public void testParsingPrintedEmptyFirstColumn(final CSVFormat.Predefined format) throws Exception {
1494 final String[][] lines = { { "a", "b" }, { "", "x" } };
1495 final StringWriter buf = new StringWriter();
1496 try (CSVPrinter printer = new CSVPrinter(buf, format.getFormat())) {
1497 printer.printRecords(Stream.of(lines));
1498 }
1499 try (CSVParser csvRecords = CSVParser.builder()
1500 .setReader(new StringReader(buf.toString()))
1501 .setFormat(format.getFormat())
1502 .get()) {
1503 for (final String[] line : lines) {
1504 assertArrayEquals(line, csvRecords.nextRecord().values());
1505 }
1506 assertNull(csvRecords.nextRecord());
1507 }
1508 }
1509
1510 @Test
1511 public void testProvidedHeader() throws Exception {
1512 final Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z");
1513
1514 try (CSVParser parser = CSVFormat.DEFAULT.withHeader("A", "B", "C").parse(in)) {
1515 final Iterator<CSVRecord> records = parser.iterator();
1516
1517 for (int i = 0; i < 3; i++) {
1518 assertTrue(records.hasNext());
1519 final CSVRecord record = records.next();
1520 assertTrue(record.isMapped("A"));
1521 assertTrue(record.isMapped("B"));
1522 assertTrue(record.isMapped("C"));
1523 assertFalse(record.isMapped("NOT MAPPED"));
1524 assertEquals(record.get(0), record.get("A"));
1525 assertEquals(record.get(1), record.get("B"));
1526 assertEquals(record.get(2), record.get("C"));
1527 }
1528
1529 assertFalse(records.hasNext());
1530 }
1531 }
1532
1533 @Test
1534 public void testProvidedHeaderAuto() throws Exception {
1535 final Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z");
1536
1537 try (CSVParser parser = CSVFormat.DEFAULT.withHeader().parse(in)) {
1538 final Iterator<CSVRecord> records = parser.iterator();
1539
1540 for (int i = 0; i < 2; i++) {
1541 assertTrue(records.hasNext());
1542 final CSVRecord record = records.next();
1543 assertTrue(record.isMapped("a"));
1544 assertTrue(record.isMapped("b"));
1545 assertTrue(record.isMapped("c"));
1546 assertFalse(record.isMapped("NOT MAPPED"));
1547 assertEquals(record.get(0), record.get("a"));
1548 assertEquals(record.get(1), record.get("b"));
1549 assertEquals(record.get(2), record.get("c"));
1550 }
1551
1552 assertFalse(records.hasNext());
1553 }
1554 }
1555
1556 @Test
1557 public void testRepeatedHeadersAreReturnedInCSVRecordHeaderNames() throws IOException {
1558 final Reader in = new StringReader("header1,header2,header1\n1,2,3\n4,5,6");
1559 try (CSVParser parser = CSVFormat.DEFAULT.withFirstRecordAsHeader().withTrim().parse(in)) {
1560 final Iterator<CSVRecord> records = parser.iterator();
1561 final CSVRecord record = records.next();
1562 @SuppressWarnings("resource")
1563 final CSVParser recordParser = record.getParser();
1564 assertEquals(Arrays.asList("header1", "header2", "header1"), recordParser.getHeaderNames());
1565 }
1566 }
1567
1568 @Test
1569 public void testRoundtrip() throws Exception {
1570 final StringWriter out = new StringWriter();
1571 final String data = "a,b,c\r\n1,2,3\r\nx,y,z\r\n";
1572 try (CSVPrinter printer = new CSVPrinter(out, CSVFormat.DEFAULT);
1573 CSVParser parse = CSVParser.parse(data, CSVFormat.DEFAULT)) {
1574 for (final CSVRecord record : parse) {
1575 printer.printRecord(record);
1576 }
1577 assertEquals(data, out.toString());
1578 }
1579 }
1580
1581 @Test
1582 public void testSkipAutoHeader() throws Exception {
1583 final Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z");
1584 try (CSVParser parser = CSVFormat.DEFAULT.withHeader().parse(in)) {
1585 final Iterator<CSVRecord> records = parser.iterator();
1586 final CSVRecord record = records.next();
1587 assertEquals("1", record.get("a"));
1588 assertEquals("2", record.get("b"));
1589 assertEquals("3", record.get("c"));
1590 }
1591 }
1592
1593 @Test
1594 public void testSkipHeaderOverrideDuplicateHeaders() throws Exception {
1595 final Reader in = new StringReader("a,a,a\n1,2,3\nx,y,z");
1596 try (CSVParser parser = CSVFormat.DEFAULT.withHeader("X", "Y", "Z").withSkipHeaderRecord().parse(in)) {
1597 final Iterator<CSVRecord> records = parser.iterator();
1598 final CSVRecord record = records.next();
1599 assertEquals("1", record.get("X"));
1600 assertEquals("2", record.get("Y"));
1601 assertEquals("3", record.get("Z"));
1602 }
1603 }
1604
1605 @Test
1606 public void testSkipSetAltHeaders() throws Exception {
1607 final Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z");
1608 try (CSVParser parser = CSVFormat.DEFAULT.withHeader("X", "Y", "Z").withSkipHeaderRecord().parse(in)) {
1609 final Iterator<CSVRecord> records = parser.iterator();
1610 final CSVRecord record = records.next();
1611 assertEquals("1", record.get("X"));
1612 assertEquals("2", record.get("Y"));
1613 assertEquals("3", record.get("Z"));
1614 }
1615 }
1616
1617 @Test
1618 public void testSkipSetHeader() throws Exception {
1619 final Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z");
1620 try (CSVParser parser = CSVFormat.DEFAULT.withHeader("a", "b", "c").withSkipHeaderRecord().parse(in)) {
1621 final Iterator<CSVRecord> records = parser.iterator();
1622 final CSVRecord record = records.next();
1623 assertEquals("1", record.get("a"));
1624 assertEquals("2", record.get("b"));
1625 assertEquals("3", record.get("c"));
1626 }
1627 }
1628
1629 @Test
1630 @Disabled
1631 public void testStartWithEmptyLinesThenHeaders() throws Exception {
1632 final String[] codes = { "\r\n\r\n\r\nhello,\r\n\r\n\r\n", "hello,\n\n\n", "hello,\"\"\r\n\r\n\r\n", "hello,\"\"\n\n\n" };
1633 final String[][] res = { { "hello", "" }, { "" },
1634 { "" } };
1635 for (final String code : codes) {
1636 try (CSVParser parser = CSVParser.parse(code, CSVFormat.EXCEL)) {
1637 final List<CSVRecord> records = parser.getRecords();
1638 assertEquals(res.length, records.size());
1639 assertFalse(records.isEmpty());
1640 for (int i = 0; i < res.length; i++) {
1641 assertArrayEquals(res[i], records.get(i).values());
1642 }
1643 }
1644 }
1645 }
1646
1647 @Test
1648 public void testStream() throws Exception {
1649 final Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z");
1650 try (CSVParser parser = CSVFormat.DEFAULT.parse(in)) {
1651 final List<CSVRecord> list = parser.stream().collect(Collectors.toList());
1652 assertFalse(list.isEmpty());
1653 assertArrayEquals(new String[] { "a", "b", "c" }, list.get(0).values());
1654 assertArrayEquals(new String[] { "1", "2", "3" }, list.get(1).values());
1655 assertArrayEquals(new String[] { "x", "y", "z" }, list.get(2).values());
1656 }
1657 }
1658
1659 @Test
1660 public void testThrowExceptionWithLineAndPosition() throws IOException {
1661 final String csvContent = "col1,col2,col3,col4,col5,col6,col7,col8,col9,col10\nrec1,rec2,rec3,rec4,rec5,rec6,rec7,rec8,\"\"rec9\"\",rec10";
1662 final StringReader stringReader = new StringReader(csvContent);
1663
1664 final CSVFormat csvFormat = CSVFormat.DEFAULT.builder()
1665 .setHeader()
1666 .setSkipHeaderRecord(true)
1667 .get();
1668
1669 try (CSVParser csvParser = csvFormat.parse(stringReader)) {
1670 final UncheckedIOException exception = assertThrows(UncheckedIOException.class, csvParser::getRecords);
1671 assertInstanceOf(CSVException.class, exception.getCause());
1672 assertTrue(exception.getMessage().contains("Invalid character between encapsulated token and delimiter at line: 2, position: 94"),
1673 exception::getMessage);
1674 }
1675 }
1676
1677 @Test
1678 public void testTrailingDelimiter() throws Exception {
1679 final Reader in = new StringReader("a,a,a,\n\"1\",\"2\",\"3\",\nx,y,z,");
1680 try (CSVParser parser = CSVFormat.DEFAULT.withHeader("X", "Y", "Z").withSkipHeaderRecord().withTrailingDelimiter().parse(in)) {
1681 final Iterator<CSVRecord> records = parser.iterator();
1682 final CSVRecord record = records.next();
1683 assertEquals("1", record.get("X"));
1684 assertEquals("2", record.get("Y"));
1685 assertEquals("3", record.get("Z"));
1686 assertEquals(3, record.size());
1687 }
1688 }
1689
1690 @Test
1691 public void testTrim() throws Exception {
1692 final Reader in = new StringReader("a,a,a\n\" 1 \",\" 2 \",\" 3 \"\nx,y,z");
1693 try (CSVParser parser = CSVFormat.DEFAULT.withHeader("X", "Y", "Z").withSkipHeaderRecord().withTrim().parse(in)) {
1694 final Iterator<CSVRecord> records = parser.iterator();
1695 final CSVRecord record = records.next();
1696 assertEquals("1", record.get("X"));
1697 assertEquals("2", record.get("Y"));
1698 assertEquals("3", record.get("Z"));
1699 assertEquals(3, record.size());
1700 }
1701 }
1702
1703 private void validateLineNumbers(final String lineSeparator) throws IOException {
1704 try (CSVParser parser = CSVParser.parse("a" + lineSeparator + "b" + lineSeparator + "c", CSVFormat.DEFAULT.withRecordSeparator(lineSeparator))) {
1705 assertEquals(0, parser.getCurrentLineNumber());
1706 assertNotNull(parser.nextRecord());
1707 assertEquals(1, parser.getCurrentLineNumber());
1708 assertNotNull(parser.nextRecord());
1709 assertEquals(2, parser.getCurrentLineNumber());
1710 assertNotNull(parser.nextRecord());
1711
1712 assertEquals(3, parser.getCurrentLineNumber());
1713 assertNull(parser.nextRecord());
1714
1715 assertEquals(3, parser.getCurrentLineNumber());
1716 }
1717 }
1718
1719 private void validateRecordNumbers(final String lineSeparator) throws IOException {
1720 try (CSVParser parser = CSVParser.parse("a" + lineSeparator + "b" + lineSeparator + "c", CSVFormat.DEFAULT.withRecordSeparator(lineSeparator))) {
1721 CSVRecord record;
1722 assertEquals(0, parser.getRecordNumber());
1723 assertNotNull(record = parser.nextRecord());
1724 assertEquals(1, record.getRecordNumber());
1725 assertEquals(1, parser.getRecordNumber());
1726 assertNotNull(record = parser.nextRecord());
1727 assertEquals(2, record.getRecordNumber());
1728 assertEquals(2, parser.getRecordNumber());
1729 assertNotNull(record = parser.nextRecord());
1730 assertEquals(3, record.getRecordNumber());
1731 assertEquals(3, parser.getRecordNumber());
1732 assertNull(record = parser.nextRecord());
1733 assertEquals(3, parser.getRecordNumber());
1734 }
1735 }
1736
1737 private void validateRecordPosition(final String lineSeparator) throws IOException {
1738 final String nl = lineSeparator;
1739 final String code = "a,b,c" + lineSeparator + "1,2,3" + lineSeparator +
1740
1741 "'A" + nl + "A','B" + nl + "B',CC" + lineSeparator +
1742
1743
1744 "\u00c4,\u00d6,\u00dc" + lineSeparator + "EOF,EOF,EOF";
1745 final CSVFormat format = CSVFormat.newFormat(',').withQuote('\'').withRecordSeparator(lineSeparator);
1746 final long positionRecord3;
1747 try (CSVParser parser = CSVParser.parse(code, format)) {
1748 CSVRecord record;
1749 assertEquals(0, parser.getRecordNumber());
1750
1751 assertNotNull(record = parser.nextRecord());
1752 assertEquals(1, record.getRecordNumber());
1753 assertEquals(code.indexOf('a'), record.getCharacterPosition());
1754
1755 assertNotNull(record = parser.nextRecord());
1756 assertEquals(2, record.getRecordNumber());
1757 assertEquals(code.indexOf('1'), record.getCharacterPosition());
1758
1759 assertNotNull(record = parser.nextRecord());
1760 positionRecord3 = record.getCharacterPosition();
1761 assertEquals(3, record.getRecordNumber());
1762 assertEquals(code.indexOf("'A"), record.getCharacterPosition());
1763 assertEquals("A" + lineSeparator + "A", record.get(0));
1764 assertEquals("B" + lineSeparator + "B", record.get(1));
1765 assertEquals("CC", record.get(2));
1766
1767 assertNotNull(record = parser.nextRecord());
1768 assertEquals(4, record.getRecordNumber());
1769 assertEquals(code.indexOf('\u00c4'), record.getCharacterPosition());
1770
1771 assertNotNull(record = parser.nextRecord());
1772 assertEquals(5, record.getRecordNumber());
1773 assertEquals(code.indexOf("EOF"), record.getCharacterPosition());
1774 }
1775
1776 try (CSVParser parser = CSVParser.builder()
1777 .setReader(new StringReader(code.substring((int) positionRecord3)))
1778 .setFormat(format)
1779 .setCharacterOffset(positionRecord3)
1780 .setRecordNumber(3)
1781 .get()) {
1782 CSVRecord record;
1783
1784 assertNotNull(record = parser.nextRecord());
1785 assertEquals(3, record.getRecordNumber());
1786 assertEquals(code.indexOf("'A"), record.getCharacterPosition());
1787 assertEquals("A" + lineSeparator + "A", record.get(0));
1788 assertEquals("B" + lineSeparator + "B", record.get(1));
1789 assertEquals("CC", record.get(2));
1790
1791 assertNotNull(record = parser.nextRecord());
1792 assertEquals(4, record.getRecordNumber());
1793 assertEquals(code.indexOf('\u00c4'), record.getCharacterPosition());
1794 assertEquals("\u00c4", record.get(0));
1795 }
1796 try (CSVParser parser = new CSVParser(new StringReader(code.substring((int) positionRecord3)), format, positionRecord3, 3)) {
1797 CSVRecord record;
1798
1799 assertNotNull(record = parser.nextRecord());
1800 assertEquals(3, record.getRecordNumber());
1801 assertEquals(code.indexOf("'A"), record.getCharacterPosition());
1802 assertEquals("A" + lineSeparator + "A", record.get(0));
1803 assertEquals("B" + lineSeparator + "B", record.get(1));
1804 assertEquals("CC", record.get(2));
1805
1806 assertNotNull(record = parser.nextRecord());
1807 assertEquals(4, record.getRecordNumber());
1808 assertEquals(code.indexOf('\u00c4'), record.getCharacterPosition());
1809 assertEquals("\u00c4", record.get(0));
1810 }
1811 }
1812 }