diff --git a/pom.xml b/pom.xml index 617587c1..142e253a 100644 --- a/pom.xml +++ b/pom.xml @@ -228,6 +228,38 @@ + + + + org.apache.rat + apache-rat-plugin + + + + + src/test/resources/org/apache/commons/csv/empty.txt + src/test/resources/org/apache/commons/csv/csv-167/sample1.csv + src/test/resources/org/apache/commons/csv/CSV-198/optd_por_public.csv + src/test/resources/org/apache/commons/csv/CSV-213/999751170.patch.csv + src/test/resources/org/apache/commons/csv/CSVFileParser/bom.csv + src/test/resources/org/apache/commons/csv/CSVFileParser/test.csv + src/test/resources/org/apache/commons/csv/CSVFileParser/test_default.txt + src/test/resources/org/apache/commons/csv/CSVFileParser/test_default_comment.txt + src/test/resources/org/apache/commons/csv/CSVFileParser/test_rfc4180.txt + src/test/resources/org/apache/commons/csv/CSVFileParser/test_rfc4180_trim.txt + src/test/resources/org/apache/commons/csv/CSVFileParser/testCSV85.csv + src/test/resources/org/apache/commons/csv/CSVFileParser/testCSV85_default.txt + src/test/resources/org/apache/commons/csv/CSVFileParser/testCSV85_ignoreEmpty.txt + + src/test/resources/org/apache/commons/csv/ferc.gov/contract.txt + src/test/resources/org/apache/commons/csv/ferc.gov/transaction.txt + src/test/resources/**/*.bin + src/test/resources/org/apache/commons/csv/CSV-259/sample.txt + src/test/resources/org/apache/commons/csv/CSVFileParser/testCSV246.csv + src/test/resources/org/apache/commons/csv/CSVFileParser/testCSV246_checkWithNoComment.txt + + + @@ -277,36 +309,9 @@ maven-pmd-plugin - - org.apache.rat apache-rat-plugin - - - - - src/test/resources/org/apache/commons/csv/csv-167/sample1.csv - src/test/resources/org/apache/commons/csv/CSV-198/optd_por_public.csv - src/test/resources/org/apache/commons/csv/CSV-213/999751170.patch.csv - src/test/resources/org/apache/commons/csv/CSVFileParser/bom.csv - src/test/resources/org/apache/commons/csv/CSVFileParser/test.csv - src/test/resources/org/apache/commons/csv/CSVFileParser/test_default.txt - src/test/resources/org/apache/commons/csv/CSVFileParser/test_default_comment.txt - src/test/resources/org/apache/commons/csv/CSVFileParser/test_rfc4180.txt - src/test/resources/org/apache/commons/csv/CSVFileParser/test_rfc4180_trim.txt - src/test/resources/org/apache/commons/csv/CSVFileParser/testCSV85.csv - src/test/resources/org/apache/commons/csv/CSVFileParser/testCSV85_default.txt - src/test/resources/org/apache/commons/csv/CSVFileParser/testCSV85_ignoreEmpty.txt - - src/test/resources/org/apache/commons/csv/ferc.gov/contract.txt - src/test/resources/org/apache/commons/csv/ferc.gov/transaction.txt - src/test/resources/**/*.bin - src/test/resources/org/apache/commons/csv/CSV-259/sample.txt - src/test/resources/org/apache/commons/csv/CSVFileParser/testCSV246.csv - src/test/resources/org/apache/commons/csv/CSVFileParser/testCSV246_checkWithNoComment.txt - - @@ -384,34 +389,9 @@ - org.apache.rat apache-rat-plugin - ${commons.rat.version} - - - - src/test/resources/csv-167/sample1.csv - src/test/resources/CSV-198/optd_por_public.csv - src/test/resources/CSV-213/999751170.patch.csv - src/test/resources/CSVFileParser/bom.csv - src/test/resources/CSVFileParser/test.csv - src/test/resources/CSVFileParser/test_default.txt - src/test/resources/CSVFileParser/test_default_comment.txt - src/test/resources/CSVFileParser/test_rfc4180.txt - src/test/resources/CSVFileParser/test_rfc4180_trim.txt - src/test/resources/CSVFileParser/testCSV85.csv - src/test/resources/CSVFileParser/testCSV85_default.txt - src/test/resources/CSVFileParser/testCSV85_ignoreEmpty.txt - src/test/resources/ferc.gov/contract.txt - src/test/resources/ferc.gov/transaction.txt - src/test/resources/**/*.bin - src/test/resources/CSV-259/sample.txt - src/test/resources/CSVFileParser/testCSV246.csv - src/test/resources/CSVFileParser/testCSV246_checkWithNoComment.txt - - diff --git a/src/test/java/org/apache/commons/csv/CSVFileParserTest.java b/src/test/java/org/apache/commons/csv/CSVFileParserTest.java index 2362aac3..da1af46f 100644 --- a/src/test/java/org/apache/commons/csv/CSVFileParserTest.java +++ b/src/test/java/org/apache/commons/csv/CSVFileParserTest.java @@ -25,11 +25,11 @@ import static org.junit.jupiter.api.Assertions.fail; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; -import java.io.FilenameFilter; import java.io.IOException; import java.net.URL; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.util.Arrays; import java.util.stream.Stream; @@ -41,7 +41,7 @@ import org.junit.jupiter.params.provider.MethodSource; */ public class CSVFileParserTest { - private static final File BASE = new File("src/test/resources/org/apache/commons/csv/CSVFileParser"); + private static final File BASE_DIR = new File("src/test/resources/org/apache/commons/csv/CSVFileParser"); private String readTestData(final BufferedReader reader) throws IOException { String line; @@ -52,8 +52,7 @@ public class CSVFileParserTest { } public static Stream generateData() { - final FilenameFilter fileNameFilter = (dir, name) -> name.startsWith("test") && name.endsWith(".txt"); - final File[] files = BASE.listFiles(fileNameFilter); + final File[] files = BASE_DIR.listFiles((dir, name) -> name.startsWith("test") && name.endsWith(".txt")); return files != null ? Stream.of(files) : Stream.empty(); } @@ -88,7 +87,7 @@ public class CSVFileParserTest { // Now parse the file and compare against the expected results // We use a buffered reader internally so no need to create one here. - try (final CSVParser parser = CSVParser.parse(new File(BASE, split[0]), Charset.defaultCharset(), format)) { + try (final CSVParser parser = CSVParser.parse(new File(BASE_DIR, split[0]), Charset.defaultCharset(), format)) { for (final CSVRecord record : parser) { String parsed = Arrays.toString(record.values()); final String comment = record.getComment(); diff --git a/src/test/java/org/apache/commons/csv/CSVParserTest.java b/src/test/java/org/apache/commons/csv/CSVParserTest.java index 7976ae80..1640780a 100644 --- a/src/test/java/org/apache/commons/csv/CSVParserTest.java +++ b/src/test/java/org/apache/commons/csv/CSVParserTest.java @@ -75,8 +75,8 @@ public class CSVParserTest { private static final String CSV_INPUT_2 = "a,b,1 2"; - private static final String[][] RESULT = { { "a", "b", "c", "d" }, { "a", "b", "1 2" }, { "foo baar", "b", "" }, - { "foo\n,,\n\",,\n\"", "d", "e" } }; + private static final String[][] RESULT = {{"a", "b", "c", "d"}, {"a", "b", "1 2"}, {"foo baar", "b", ""}, + {"foo\n,,\n\",,\n\"", "d", "e"}}; private BOMInputStream createBOMInputStream(final String resource) throws IOException { final URL url = ClassLoader.getSystemClassLoader().getResource(resource); @@ -89,84 +89,6 @@ public class CSVParserTest { } } - @Test - public void testParseWithDelimiterWithQuote() throws IOException { - final String source = "'a,b,c',xyz"; - final CSVFormat csvFormat = CSVFormat.DEFAULT.withQuote('\''); - try (CSVParser csvParser = csvFormat.parse(new StringReader(source))) { - final CSVRecord csvRecord = csvParser.nextRecord(); - assertEquals("a,b,c", csvRecord.get(0)); - assertEquals("xyz", csvRecord.get(1)); - } - } - - @Test - public void testParseWithDelimiterStringWithQuote() throws IOException { - final String source = "'a[|]b[|]c'[|]xyz\r\nabc[abc][|]xyz"; - final CSVFormat csvFormat = CSVFormat.DEFAULT.builder().setDelimiter("[|]").setQuote('\'').build(); - try (CSVParser csvParser = csvFormat.parse(new StringReader(source))) { - CSVRecord csvRecord = csvParser.nextRecord(); - assertEquals("a[|]b[|]c", csvRecord.get(0)); - assertEquals("xyz", csvRecord.get(1)); - csvRecord = csvParser.nextRecord(); - assertEquals("abc[abc]", csvRecord.get(0)); - assertEquals("xyz", csvRecord.get(1)); - } - } - - @Test - public void testParseWithDelimiterWithEscape() throws IOException { - final String source = "a!,b!,c,xyz"; - final CSVFormat csvFormat = CSVFormat.DEFAULT.withEscape('!'); - try (CSVParser csvParser = csvFormat.parse(new StringReader(source))) { - final CSVRecord csvRecord = csvParser.nextRecord(); - assertEquals("a,b,c", csvRecord.get(0)); - assertEquals("xyz", csvRecord.get(1)); - } - } - - @Test - public void testParseWithDelimiterStringWithEscape() throws IOException { - final String source = "a![!|!]b![|]c[|]xyz\r\nabc[abc][|]xyz"; - final CSVFormat csvFormat = CSVFormat.DEFAULT.builder().setDelimiter("[|]").setEscape('!').build(); - try (CSVParser csvParser = csvFormat.parse(new StringReader(source))) { - CSVRecord csvRecord = csvParser.nextRecord(); - assertEquals("a[|]b![|]c", csvRecord.get(0)); - assertEquals("xyz", csvRecord.get(1)); - csvRecord = csvParser.nextRecord(); - assertEquals("abc[abc]", csvRecord.get(0)); - assertEquals("xyz", csvRecord.get(1)); - } - } - - @Test - public void testParseWithQuoteWithEscape() throws IOException { - final String source = "'a?,b?,c?d',xyz"; - final CSVFormat csvFormat = CSVFormat.DEFAULT.withQuote('\'').withEscape('?'); - try (CSVParser csvParser = csvFormat.parse(new StringReader(source))) { - final CSVRecord csvRecord = csvParser.nextRecord(); - assertEquals("a,b,c?d", csvRecord.get(0)); - assertEquals("xyz", csvRecord.get(1)); - } - } - - @Test - public void testParseWithQuoteThrowsException() { - final CSVFormat csvFormat = CSVFormat.DEFAULT.withQuote('\''); - assertThrows(IOException.class, () -> csvFormat.parse(new StringReader("'a,b,c','")).nextRecord()); - assertThrows(IOException.class, () -> csvFormat.parse(new StringReader("'a,b,c'abc,xyz")).nextRecord()); - assertThrows(IOException.class, () -> csvFormat.parse(new StringReader("'abc'a,b,c',xyz")).nextRecord()); - } - - @Test - public void testNotValueCSV() throws IOException { - final String source = "#"; - final CSVFormat csvFormat = CSVFormat.DEFAULT.withCommentMarker('#'); - final CSVParser csvParser = csvFormat.parse(new StringReader(source)); - final CSVRecord csvRecord = csvParser.nextRecord(); - assertNull(csvRecord); - } - @Test public void testBackslashEscaping() throws IOException { @@ -185,15 +107,15 @@ public class CSVParserTest { + " 8 , \"quoted \"\" /\" // string\" \n" // don't eat spaces + "9, /\n \n" // escaped newline + ""; - final String[][] res = { { "one", "two", "three" }, // 0 - { "", "" }, // 1 - { "'", "'" }, // 2 - { "'", "'" }, // 3 - { "'", "'" }, // 4 - { ",", "," }, // 5 - { "/", "/" }, // 6 - { "/", "/" }, // 7 - { " 8 ", " \"quoted \"\" /\" / string\" " }, { "9", " \n " }, }; + final String[][] res = {{"one", "two", "three"}, // 0 + {"", ""}, // 1 + {"'", "'"}, // 2 + {"'", "'"}, // 3 + {"'", "'"}, // 4 + {",", ","}, // 5 + {"/", "/"}, // 6 + {"/", "/"}, // 7 + {" 8 ", " \"quoted \"\" /\" / string\" "}, {"9", " \n "},}; final CSVFormat format = CSVFormat.newFormat(',').withQuote('\'').withRecordSeparator(CRLF).withEscape('/') .withIgnoreEmptyLines(); @@ -217,9 +139,9 @@ public class CSVParserTest { + " \t , , \n" // 2) + " // , /, , /,\n" // 3) + ""; - final String[][] res = { { " ", " ", " " }, // 1 - { " \t ", " ", " " }, // 2 - { " / ", " , ", " ," }, // 3 + final String[][] res = {{" ", " ", " "}, // 1 + {" \t ", " ", " "}, // 2 + {" / ", " , ", " ,"}, // 3 }; final CSVFormat format = CSVFormat.newFormat(',').withRecordSeparator(CRLF).withEscape('/') @@ -238,11 +160,11 @@ public class CSVParserTest { public void testBackslashEscapingOld() throws IOException { 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" + "\"a\\\\\"\n" + "a\\,b\n" + "\"a\\\\,b\""; - final String[][] res = { { "one", "two", "three" }, { "on\\\"e", "two" }, { "on\"e", "two" }, - { "one", "tw\"o" }, { "one", "t\\,wo" }, // backslash in quotes only escapes a delimiter (",") - { "one", "two", "th,ree" }, { "a\\\\" }, // backslash in quotes only escapes a delimiter (",") - { "a\\", "b" }, // a backslash must be returned - { "a\\\\,b" } // backslash in quotes only escapes a delimiter (",") + final String[][] res = {{"one", "two", "three"}, {"on\\\"e", "two"}, {"on\"e", "two"}, {"one", "tw\"o"}, + {"one", "t\\,wo"}, // backslash in quotes only escapes a delimiter (",") + {"one", "two", "th,ree"}, {"a\\\\"}, // backslash in quotes only escapes a delimiter (",") + {"a\\", "b"}, // a backslash must be returned + {"a\\\\,b"} // backslash in quotes only escapes a delimiter (",") }; try (final CSVParser parser = CSVParser.parse(code, CSVFormat.DEFAULT)) { final List records = parser.getRecords(); @@ -365,11 +287,11 @@ public class CSVParserTest { + "#,\"\"\n" // 3) + "# Final comment\n"// 4) ; - final String[][] res = { { "a", "b#" }, { "\n", " ", "#" }, { "#", "" }, { "# Final comment" } }; + final String[][] res = {{"a", "b#"}, {"\n", " ", "#"}, {"#", ""}, {"# Final comment"}}; CSVFormat format = CSVFormat.DEFAULT; assertFalse(format.isCommentMarkerSet()); - final String[][] res_comments = { { "a", "b#" }, { "\n", " ", "#" }, }; + final String[][] res_comments = {{"a", "b#"}, {"\n", " ", "#"},}; try (final CSVParser parser = CSVParser.parse(code, format)) { final List records = parser.getRecords(); @@ -399,7 +321,8 @@ public class CSVParserTest { @Test public void testEmptyFile() throws Exception { - try (final CSVParser parser = CSVParser.parse("", CSVFormat.DEFAULT)) { + try (final CSVParser parser = CSVParser.parse(Paths.get("src/test/resources/org/apache/commons/csv/empty.txt"), + StandardCharsets.UTF_8, CSVFormat.DEFAULT)) { assertNull(parser.nextRecord()); } } @@ -414,8 +337,8 @@ public class CSVParserTest { @Test public void testEmptyLineBehaviorCSV() throws Exception { - 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" }; - final String[][] res = { { "hello", "" } // CSV format ignores empty lines + 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"}; + final String[][] res = {{"hello", ""} // CSV format ignores empty lines }; for (final String code : codes) { try (final CSVParser parser = CSVParser.parse(code, CSVFormat.DEFAULT)) { @@ -431,9 +354,9 @@ public class CSVParserTest { @Test public void testEmptyLineBehaviorExcel() throws Exception { - 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" }; - final String[][] res = { { "hello", "" }, { "" }, // Excel format does not ignore empty lines - { "" } }; + 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"}; + final String[][] res = {{"hello", ""}, {""}, // Excel format does not ignore empty lines + {""}}; for (final String code : codes) { try (final CSVParser parser = CSVParser.parse(code, CSVFormat.EXCEL)) { final List records = parser.getRecords(); @@ -446,13 +369,20 @@ public class CSVParserTest { } } + @Test + public void testEmptyString() throws Exception { + try (final CSVParser parser = CSVParser.parse("", CSVFormat.DEFAULT)) { + assertNull(parser.nextRecord()); + } + } + @Test public void testEndOfFileBehaviorCSV() throws Exception { - final String[] codes = { "hello,\r\n\r\nworld,\r\n", "hello,\r\n\r\nworld,", "hello,\r\n\r\nworld,\"\"\r\n", + 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,\"\"", "hello,\r\n\r\nworld,\n", "hello,\r\n\r\nworld,", "hello,\r\n\r\nworld,\"\"\n", - "hello,\r\n\r\nworld,\"\"" }; - final String[][] res = { { "hello", "" }, // CSV format ignores empty lines - { "world", "" } }; + "hello,\r\n\r\nworld,\"\""}; + final String[][] res = {{"hello", ""}, // CSV format ignores empty lines + {"world", ""}}; for (final String code : codes) { try (final CSVParser parser = CSVParser.parse(code, CSVFormat.DEFAULT)) { final List records = parser.getRecords(); @@ -467,11 +397,11 @@ public class CSVParserTest { @Test public void testEndOfFileBehaviorExcel() throws Exception { - final String[] codes = { "hello,\r\n\r\nworld,\r\n", "hello,\r\n\r\nworld,", "hello,\r\n\r\nworld,\"\"\r\n", + 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,\"\"", "hello,\r\n\r\nworld,\n", "hello,\r\n\r\nworld,", "hello,\r\n\r\nworld,\"\"\n", - "hello,\r\n\r\nworld,\"\"" }; - final String[][] res = { { "hello", "" }, { "" }, // Excel format does not ignore empty lines - { "world", "" } }; + "hello,\r\n\r\nworld,\"\""}; + final String[][] res = {{"hello", ""}, {""}, // Excel format does not ignore empty lines + {"world", ""}}; for (final String code : codes) { try (final CSVParser parser = CSVParser.parse(code, CSVFormat.EXCEL)) { @@ -489,8 +419,8 @@ public class CSVParserTest { public void testExcelFormat1() throws IOException { 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"; - final String[][] res = { { "value1", "value2", "value3", "value4" }, { "a", "b", "c", "d" }, - { " x", "", "", "" }, { "" }, { "\"hello\"", " \"world\"", "abc\ndef", "" } }; + final String[][] res = {{"value1", "value2", "value3", "value4"}, {"a", "b", "c", "d"}, {" x", "", "", ""}, + {""}, {"\"hello\"", " \"world\"", "abc\ndef", ""}}; try (final CSVParser parser = CSVParser.parse(code, CSVFormat.EXCEL)) { final List records = parser.getRecords(); assertEquals(res.length, records.size()); @@ -504,7 +434,7 @@ public class CSVParserTest { @Test public void testExcelFormat2() throws Exception { final String code = "foo,baar\r\n\r\nhello,\r\n\r\nworld,\r\n"; - final String[][] res = { { "foo", "baar" }, { "" }, { "hello", "" }, { "" }, { "world", "" } }; + final String[][] res = {{"foo", "baar"}, {""}, {"hello", ""}, {""}, {"world", ""}}; try (final CSVParser parser = CSVParser.parse(code, CSVFormat.EXCEL)) { final List records = parser.getRecords(); assertEquals(res.length, records.size()); @@ -570,9 +500,9 @@ public class CSVParserTest { records.add(record); } assertEquals(3, records.size()); - assertArrayEquals(new String[] { "a", "b", "c" }, records.get(0).values()); - assertArrayEquals(new String[] { "1", "2", "3" }, records.get(1).values()); - assertArrayEquals(new String[] { "x", "y", "z" }, records.get(2).values()); + assertArrayEquals(new String[] {"a", "b", "c"}, records.get(0).values()); + assertArrayEquals(new String[] {"1", "2", "3"}, records.get(1).values()); + assertArrayEquals(new String[] {"x", "y", "z"}, records.get(2).values()); } } @@ -865,12 +795,12 @@ public class CSVParserTest { assertTrue(iterator.hasNext()); assertThrows(UnsupportedOperationException.class, iterator::remove); - assertArrayEquals(new String[] { "a", "b", "c" }, iterator.next().values()); - assertArrayEquals(new String[] { "1", "2", "3" }, iterator.next().values()); + assertArrayEquals(new String[] {"a", "b", "c"}, iterator.next().values()); + assertArrayEquals(new String[] {"1", "2", "3"}, iterator.next().values()); assertTrue(iterator.hasNext()); assertTrue(iterator.hasNext()); assertTrue(iterator.hasNext()); - assertArrayEquals(new String[] { "x", "y", "z" }, iterator.next().values()); + assertArrayEquals(new String[] {"x", "y", "z"}, iterator.next().values()); assertFalse(iterator.hasNext()); assertThrows(NoSuchElementException.class, iterator::next); @@ -1033,6 +963,15 @@ public class CSVParserTest { } } + @Test + public void testNotValueCSV() throws IOException { + final String source = "#"; + final CSVFormat csvFormat = CSVFormat.DEFAULT.withCommentMarker('#'); + final CSVParser csvParser = csvFormat.parse(new StringReader(source)); + final CSVRecord csvRecord = csvParser.nextRecord(); + assertNull(csvRecord); + } + @Test public void testParse() throws Exception { final ClassLoader loader = ClassLoader.getSystemClassLoader(); @@ -1114,6 +1053,75 @@ public class CSVParserTest { () -> CSVParser.parse(new URL("https://commons.apache.org"), Charset.defaultCharset(), null)); } + @Test + public void testParseWithDelimiterStringWithEscape() throws IOException { + final String source = "a![!|!]b![|]c[|]xyz\r\nabc[abc][|]xyz"; + final CSVFormat csvFormat = CSVFormat.DEFAULT.builder().setDelimiter("[|]").setEscape('!').build(); + try (CSVParser csvParser = csvFormat.parse(new StringReader(source))) { + CSVRecord csvRecord = csvParser.nextRecord(); + assertEquals("a[|]b![|]c", csvRecord.get(0)); + assertEquals("xyz", csvRecord.get(1)); + csvRecord = csvParser.nextRecord(); + assertEquals("abc[abc]", csvRecord.get(0)); + assertEquals("xyz", csvRecord.get(1)); + } + } + + @Test + public void testParseWithDelimiterStringWithQuote() throws IOException { + final String source = "'a[|]b[|]c'[|]xyz\r\nabc[abc][|]xyz"; + final CSVFormat csvFormat = CSVFormat.DEFAULT.builder().setDelimiter("[|]").setQuote('\'').build(); + try (CSVParser csvParser = csvFormat.parse(new StringReader(source))) { + CSVRecord csvRecord = csvParser.nextRecord(); + assertEquals("a[|]b[|]c", csvRecord.get(0)); + assertEquals("xyz", csvRecord.get(1)); + csvRecord = csvParser.nextRecord(); + assertEquals("abc[abc]", csvRecord.get(0)); + assertEquals("xyz", csvRecord.get(1)); + } + } + + @Test + public void testParseWithDelimiterWithEscape() throws IOException { + final String source = "a!,b!,c,xyz"; + final CSVFormat csvFormat = CSVFormat.DEFAULT.withEscape('!'); + try (CSVParser csvParser = csvFormat.parse(new StringReader(source))) { + final CSVRecord csvRecord = csvParser.nextRecord(); + assertEquals("a,b,c", csvRecord.get(0)); + assertEquals("xyz", csvRecord.get(1)); + } + } + + @Test + public void testParseWithDelimiterWithQuote() throws IOException { + final String source = "'a,b,c',xyz"; + final CSVFormat csvFormat = CSVFormat.DEFAULT.withQuote('\''); + try (CSVParser csvParser = csvFormat.parse(new StringReader(source))) { + final CSVRecord csvRecord = csvParser.nextRecord(); + assertEquals("a,b,c", csvRecord.get(0)); + assertEquals("xyz", csvRecord.get(1)); + } + } + + @Test + public void testParseWithQuoteThrowsException() { + final CSVFormat csvFormat = CSVFormat.DEFAULT.withQuote('\''); + assertThrows(IOException.class, () -> csvFormat.parse(new StringReader("'a,b,c','")).nextRecord()); + assertThrows(IOException.class, () -> csvFormat.parse(new StringReader("'a,b,c'abc,xyz")).nextRecord()); + assertThrows(IOException.class, () -> csvFormat.parse(new StringReader("'abc'a,b,c',xyz")).nextRecord()); + } + + @Test + public void testParseWithQuoteWithEscape() throws IOException { + final String source = "'a?,b?,c?d',xyz"; + final CSVFormat csvFormat = CSVFormat.DEFAULT.withQuote('\'').withEscape('?'); + try (CSVParser csvParser = csvFormat.parse(new StringReader(source))) { + final CSVRecord csvRecord = csvParser.nextRecord(); + assertEquals("a,b,c?d", csvRecord.get(0)); + assertEquals("xyz", csvRecord.get(1)); + } + } + @Test public void testProvidedHeader() throws Exception { final Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z"); @@ -1222,10 +1230,10 @@ public class CSVParserTest { @Test @Disabled public void testStartWithEmptyLinesThenHeaders() throws Exception { - 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" }; - final String[][] res = { { "hello", "" }, { "" }, // Excel format does not ignore empty lines - { "" } }; + 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"}; + final String[][] res = {{"hello", ""}, {""}, // Excel format does not ignore empty lines + {""}}; for (final String code : codes) { try (final CSVParser parser = CSVParser.parse(code, CSVFormat.EXCEL)) { final List records = parser.getRecords(); @@ -1243,9 +1251,9 @@ public class CSVParserTest { final Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z"); final List list = CSVFormat.DEFAULT.parse(in).stream().collect(Collectors.toList()); assertFalse(list.isEmpty()); - assertArrayEquals(new String[] { "a", "b", "c" }, list.get(0).values()); - assertArrayEquals(new String[] { "1", "2", "3" }, list.get(1).values()); - assertArrayEquals(new String[] { "x", "y", "z" }, list.get(2).values()); + assertArrayEquals(new String[] {"a", "b", "c"}, list.get(0).values()); + assertArrayEquals(new String[] {"1", "2", "3"}, list.get(1).values()); + assertArrayEquals(new String[] {"x", "y", "z"}, list.get(2).values()); } @Test diff --git a/src/test/resources/org/apache/commons/csv/empty.txt b/src/test/resources/org/apache/commons/csv/empty.txt new file mode 100644 index 00000000..e69de29b