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.
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/csv/trunk@1508509 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
7af334d7d5
commit
f78b5a14ca
|
@ -449,16 +449,16 @@ public class CSVFormat implements Serializable {
|
|||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -236,6 +236,9 @@ public class CSVParser implements Iterable<CSVRecord>, Closeable {
|
|||
|
||||
/**
|
||||
* 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 Iterable<CSVRecord>, Closeable {
|
|||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
if (isClosed()) {
|
||||
return false;
|
||||
}
|
||||
if (current == null) {
|
||||
current = getNextRecord();
|
||||
}
|
||||
|
@ -317,6 +323,9 @@ public class CSVParser implements Iterable<CSVRecord>, Closeable {
|
|||
}
|
||||
|
||||
public CSVRecord next() {
|
||||
if (isClosed()) {
|
||||
return null;
|
||||
}
|
||||
CSVRecord next = current;
|
||||
current = null;
|
||||
|
||||
|
@ -337,4 +346,8 @@ public class CSVParser implements Iterable<CSVRecord>, Closeable {
|
|||
};
|
||||
}
|
||||
|
||||
public boolean isClosed() {
|
||||
return lexer.isClosed();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -41,6 +41,8 @@ final class ExtendedBufferedReader extends BufferedReader {
|
|||
|
||||
/** 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 extends BufferedReader {
|
|||
}
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -148,6 +148,10 @@ abstract class Lexer implements Closeable {
|
|||
|
||||
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 Closeable {
|
|||
|
||||
/**
|
||||
* Closes resources.
|
||||
*
|
||||
* @throws IOException
|
||||
* If an I/O error occurs
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
if (in != null) {
|
||||
in.close();
|
||||
}
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,6 @@ import java.util.Map;
|
|||
import java.util.NoSuchElementException;
|
||||
|
||||
import org.junit.Assert;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -395,6 +394,19 @@ public class CSVParserTest {
|
|||
assertEquals(4, records.size());
|
||||
}
|
||||
|
||||
@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";
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue