Made CSVParser iterable to simplify the iteration over the records

git-svn-id: https://svn.apache.org/repos/asf/commons/sandbox/csv/trunk@1200024 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Emmanuel Bourg 2011-11-09 23:04:13 +00:00
parent a7bd28c496
commit 045dbbbe4a
2 changed files with 100 additions and 9 deletions

View File

@ -20,7 +20,9 @@ package org.apache.commons.csv;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import static org.apache.commons.csv.CSVParser.Token.Type.*;
@ -33,14 +35,18 @@ import static org.apache.commons.csv.CSVParser.Token.Type.*;
* <p>Parsing of a csv-string having tabs as separators,
* '"' as an optional value encapsulator, and comments starting with '#':</p>
* <pre>
* String[][] record =
* (new CSVParser(new StringReader("a\tb\nc\td"), new CSVFormat('\t','"','#'))).getAllValues();
* CSVFormat format = new CSVFormat('\t', '"', '#');
* Reader in = new StringReader("a\tb\nc\td");
* String[][] records = new CSVParser(in, format).getRecords();
* </pre>
*
* <p>Parsing of a csv-string in Excel CSV format</p>
* <p>Parsing of a csv-string in Excel CSV format, using a for-each loop:</p>
* <pre>
* String[][] record =
* (new CSVParser(new StringReader("a;b\nc;d"), CSVFormat.EXCEL)).getAllValues();
* Reader in = new StringReader("a;b\nc;d");
* CSVParser parser = new CSVParser(in, CSVFormat.EXCEL);
* for (String[] record : parser) {
* ...
* }
* </pre>
*
* <p>
@ -50,7 +56,7 @@ import static org.apache.commons.csv.CSVParser.Token.Type.*;
* <p>see <a href="package-summary.html">package documentation</a>
* for more details</p>
*/
public class CSVParser {
public class CSVParser implements Iterable<String[]> {
/** length of the initial token (content-)buffer */
private static final int INITIAL_TOKEN_LENGTH = 50;
@ -172,7 +178,7 @@ public class CSVParser {
* ('null' when end of file has been reached)
* @throws IOException on parse error or input read-failure
*/
public String[] getLine() throws IOException {
String[] getLine() throws IOException {
String[] ret = EMPTY_STRING_ARRAY;
record.clear();
while (true) {
@ -208,6 +214,49 @@ public class CSVParser {
return ret;
}
/**
* Returns an iterator on the records. IOExceptions occuring
* during the iteration are wrapped in a RuntimeException.
*/
public Iterator<String[]> iterator() {
return new Iterator<String[]>() {
String[] current;
public boolean hasNext() {
if (current == null) {
current = getNextLine();
}
return current != null;
}
public String[] next() {
String[] next = current;
current = null;
if (next == null) {
// hasNext() wasn't called before
next = getNextLine();
if (next == null) {
throw new NoSuchElementException("No more CSV records available");
}
}
return next;
}
private String[] getNextLine() {
try {
return getLine();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public void remove() { }
};
}
/**
* Returns the current line number in the input stream.
* <p/>

View File

@ -20,7 +20,11 @@ package org.apache.commons.csv;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import junit.framework.TestCase;
@ -219,7 +223,7 @@ public class CSVParserTest extends TestCase {
assertTrue(parser.getLine() == null);
}
public void testGetAllValues() throws IOException {
public void testGetRecords() throws IOException {
CSVParser parser = new CSVParser(new StringReader(code));
String[][] tmp = parser.getRecords();
assertEquals(res.length, tmp.length);
@ -518,7 +522,7 @@ public class CSVParserTest extends TestCase {
public void testUnicodeEscape() throws IOException {
String code = "abc,\\u0070\\u0075\\u0062\\u006C\\u0069\\u0063";
CSVParser parser = new CSVParser(new StringReader(code), CSVFormat.DEFAULT.withUnicodeEscapesInterpreted(true));
String[] data = parser.getLine();
String[] data = parser.iterator().next();
assertEquals(2, data.length);
assertEquals("abc", data[0]);
assertEquals("public", data[1]);
@ -565,4 +569,42 @@ public class CSVParserTest extends TestCase {
assertEquals(TOKEN + ";five;", parser.testNextToken());
assertEquals(EOF + ";six;", parser.testNextToken());
}
public void testForEach() {
List<String[]> records = new ArrayList<String[]>();
String code = "a,b,c\n1,2,3\nx,y,z";
Reader in = new StringReader(code);
for (String[] record : new CSVParser(in)) {
records.add(record);
}
assertEquals(3, records.size());
assertTrue(Arrays.equals(new String[] {"a", "b", "c"}, records.get(0)));
assertTrue(Arrays.equals(new String[]{"1", "2", "3"}, records.get(1)));
assertTrue(Arrays.equals(new String[] {"x", "y", "z"}, records.get(2)));
}
public void testIterator() {
String code = "a,b,c\n1,2,3\nx,y,z";
Iterator<String[]> iterator = new CSVParser(new StringReader(code)).iterator();
assertTrue(iterator.hasNext());
iterator.remove();
assertTrue(Arrays.equals(new String[]{"a", "b", "c"}, iterator.next()));
assertTrue(Arrays.equals(new String[]{"1", "2", "3"}, iterator.next()));
assertTrue(iterator.hasNext());
assertTrue(iterator.hasNext());
assertTrue(iterator.hasNext());
assertTrue(Arrays.equals(new String[]{"x", "y", "z"}, iterator.next()));
assertFalse(iterator.hasNext());
try {
iterator.next();
fail("NoSuchElementException expected");
} catch (NoSuchElementException e) {
// expected
}
}
}