Author: ggregory Date: Tue Jul 30 16:22:07 2013 New Revision: 1508509 URL: http://svn.apache.org/r1508509 Log: Change CSVFormat#Iterable<CSVRecord> parse(final Reader in) to return a CSVParser, which is compatible since CSVParser implements Iterable<CSVRecord>. This allows a caller to end the parsing by calling CSVParser#close() or to use CSVParser in a Java 7 try-with-resources, without tracking a reader or input stream.
Modified: commons/proper/csv/trunk/src/main/java/org/apache/commons/csv/CSVFormat.java commons/proper/csv/trunk/src/main/java/org/apache/commons/csv/CSVParser.java commons/proper/csv/trunk/src/main/java/org/apache/commons/csv/ExtendedBufferedReader.java commons/proper/csv/trunk/src/main/java/org/apache/commons/csv/Lexer.java commons/proper/csv/trunk/src/test/java/org/apache/commons/csv/CSVParserTest.java Modified: commons/proper/csv/trunk/src/main/java/org/apache/commons/csv/CSVFormat.java URL: http://svn.apache.org/viewvc/commons/proper/csv/trunk/src/main/java/org/apache/commons/csv/CSVFormat.java?rev=1508509&r1=1508508&r2=1508509&view=diff ============================================================================== --- commons/proper/csv/trunk/src/main/java/org/apache/commons/csv/CSVFormat.java (original) +++ commons/proper/csv/trunk/src/main/java/org/apache/commons/csv/CSVFormat.java Tue Jul 30 16:22:07 2013 @@ -449,16 +449,16 @@ public class CSVFormat implements Serial return quoteChar != null; } - /** - * Parses the specified content. - * - * @param in - * the input stream - * @return a stream of CSVRecord - * @throws IOException - * If an I/O error occurs - */ - public Iterable<CSVRecord> parse(final Reader in) throws IOException { + /** + * Parses the specified content. + * + * @param in + * the input stream + * @return a parser over a stream of {@link #CSVRecord}s. + * @throws IOException + * If an I/O error occurs + */ + public CSVParser parse(final Reader in) throws IOException { return new CSVParser(in, this); } Modified: commons/proper/csv/trunk/src/main/java/org/apache/commons/csv/CSVParser.java URL: http://svn.apache.org/viewvc/commons/proper/csv/trunk/src/main/java/org/apache/commons/csv/CSVParser.java?rev=1508509&r1=1508508&r2=1508509&view=diff ============================================================================== --- commons/proper/csv/trunk/src/main/java/org/apache/commons/csv/CSVParser.java (original) +++ commons/proper/csv/trunk/src/main/java/org/apache/commons/csv/CSVParser.java Tue Jul 30 16:22:07 2013 @@ -236,6 +236,9 @@ public class CSVParser implements Iterab /** * Closes resources. + * + * @throws IOException + * If an I/O error occurs */ public void close() throws IOException { if (lexer != null) { @@ -309,6 +312,9 @@ public class CSVParser implements Iterab } public boolean hasNext() { + if (isClosed()) { + return false; + } if (current == null) { current = getNextRecord(); } @@ -317,6 +323,9 @@ public class CSVParser implements Iterab } public CSVRecord next() { + if (isClosed()) { + return null; + } CSVRecord next = current; current = null; @@ -337,4 +346,8 @@ public class CSVParser implements Iterab }; } + public boolean isClosed() { + return lexer.isClosed(); + } + } Modified: commons/proper/csv/trunk/src/main/java/org/apache/commons/csv/ExtendedBufferedReader.java URL: http://svn.apache.org/viewvc/commons/proper/csv/trunk/src/main/java/org/apache/commons/csv/ExtendedBufferedReader.java?rev=1508509&r1=1508508&r2=1508509&view=diff ============================================================================== --- commons/proper/csv/trunk/src/main/java/org/apache/commons/csv/ExtendedBufferedReader.java (original) +++ commons/proper/csv/trunk/src/main/java/org/apache/commons/csv/ExtendedBufferedReader.java Tue Jul 30 16:22:07 2013 @@ -41,6 +41,8 @@ final class ExtendedBufferedReader exten /** The count of EOLs (CR/LF/CRLF) seen so far */ private long eolCounter = 0; + + private boolean closed; /** * Created extended buffered reader using default buffer-size @@ -154,4 +156,23 @@ final class ExtendedBufferedReader exten } return eolCounter + 1; // Allow for counter being incremented only at EOL } + + public boolean isClosed() { + return closed; + } + + /** + * Closes the stream. + * + * @throws IOException + * If an I/O error occurs + */ + @Override + public void close() throws IOException { + // Set ivars before calling super close() in case close() throws an IOException. + closed = true; + lastChar = END_OF_STREAM; + super.close(); + } + } Modified: commons/proper/csv/trunk/src/main/java/org/apache/commons/csv/Lexer.java URL: http://svn.apache.org/viewvc/commons/proper/csv/trunk/src/main/java/org/apache/commons/csv/Lexer.java?rev=1508509&r1=1508508&r2=1508509&view=diff ============================================================================== --- commons/proper/csv/trunk/src/main/java/org/apache/commons/csv/Lexer.java (original) +++ commons/proper/csv/trunk/src/main/java/org/apache/commons/csv/Lexer.java Tue Jul 30 16:22:07 2013 @@ -148,6 +148,10 @@ abstract class Lexer implements Closeabl abstract Token nextToken(Token reusableToken) throws IOException; + boolean isClosed() { + return in.isClosed(); + } + /** * @return true if the given char is a whitespace character */ @@ -197,10 +201,11 @@ abstract class Lexer implements Closeabl /** * Closes resources. + * + * @throws IOException + * If an I/O error occurs */ public void close() throws IOException { - if (in != null) { - in.close(); - } + in.close(); } } Modified: commons/proper/csv/trunk/src/test/java/org/apache/commons/csv/CSVParserTest.java URL: http://svn.apache.org/viewvc/commons/proper/csv/trunk/src/test/java/org/apache/commons/csv/CSVParserTest.java?rev=1508509&r1=1508508&r2=1508509&view=diff ============================================================================== --- commons/proper/csv/trunk/src/test/java/org/apache/commons/csv/CSVParserTest.java (original) +++ commons/proper/csv/trunk/src/test/java/org/apache/commons/csv/CSVParserTest.java Tue Jul 30 16:22:07 2013 @@ -39,7 +39,6 @@ import java.util.Map; import java.util.NoSuchElementException; import org.junit.Assert; - import org.junit.Ignore; import org.junit.Test; @@ -396,6 +395,19 @@ public class CSVParserTest { } @Test + public void testClose() throws Exception { + final Reader in = new StringReader("# comment\na,b,c\n1,2,3\nx,y,z"); + final CSVParser parser = CSVFormat.DEFAULT.withCommentStart('#').withHeader().parse(in); + final Iterator<CSVRecord> records = parser.iterator(); + assertTrue(records.hasNext()); + parser.close(); + assertFalse(records.hasNext()); + assertNull(records.next()); + assertFalse(records.hasNext()); + assertNull(records.next()); + } + + @Test public void testCarriageReturnEndings() throws IOException { final String code = "foo\rbaar,\rhello,world\r,kanu"; final CSVParser parser = new CSVParser(new StringReader(code)); @@ -605,22 +617,22 @@ public class CSVParserTest { @Test public void testGetLineNumberWithLF() throws Exception { - validateLineNumbers(String.valueOf(LF)); + this.validateLineNumbers(String.valueOf(LF)); } @Test public void testGetLineNumberWithCRLF() throws Exception { - validateLineNumbers(CRLF); + this.validateLineNumbers(CRLF); } @Test public void testGetLineNumberWithCR() throws Exception { - validateLineNumbers(String.valueOf(CR)); + this.validateLineNumbers(String.valueOf(CR)); } @Test public void testGetRecordNumberWithLF() throws Exception { - validateRecordNumbers(String.valueOf(LF)); + this.validateRecordNumbers(String.valueOf(LF)); } @Test @@ -649,17 +661,17 @@ public class CSVParserTest { @Test public void testGetRecordNumberWithCRLF() throws Exception { - validateRecordNumbers(CRLF); + this.validateRecordNumbers(CRLF); } @Test public void testGetRecordNumberWithCR() throws Exception { - validateRecordNumbers(String.valueOf(CR)); + this.validateRecordNumbers(String.valueOf(CR)); } @Test(expected = IllegalArgumentException.class) public void testInvalidFormat() throws Exception { - CSVFormat invalidFormat = CSVFormat.DEFAULT.withDelimiter(CR); + final CSVFormat invalidFormat = CSVFormat.DEFAULT.withDelimiter(CR); new CSVParser((Reader) null, invalidFormat); }