panda.io.LineIterator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of panda-core Show documentation
Show all versions of panda-core Show documentation
Panda Core is the core module of Panda Framework, it contains commonly used utility classes similar to apache-commons.
package panda.io;
import java.io.BufferedReader;
import java.io.Closeable;
import java.io.IOException;
import java.io.Reader;
import java.util.Iterator;
import java.util.NoSuchElementException;
import panda.lang.Exceptions;
/**
* An Iterator over the lines in a Reader
.
*
* LineIterator
holds a reference to an open Reader
. When you have
* finished with the iterator you should close the reader to free internal resources. This can be
* done by closing the reader directly, or by calling the {@link #close()} method on the iterator.
*
* The recommended usage pattern is:
*
*
* LineIterator it = Streams.lineIterator(file, "UTF-8");
* try {
* while (it.hasNext()) {
* String line = it.nextLine();
* // do something with line
* }
* }
* finally {
* it.close();
* }
*
*
*/
public class LineIterator implements Iterator, Closeable {
/** The reader that is being read. */
private final BufferedReader bufferedReader;
/** The current line. */
private String cachedLine;
/** A flag indicating if the iterator has been fully read. */
private boolean finished = false;
/**
* Constructs an iterator of the lines for a Reader
.
*
* @param reader the Reader
to read from, not null
* @throws IllegalArgumentException if the reader is null
*/
public LineIterator(final Reader reader) throws IllegalArgumentException {
if (reader == null) {
throw new IllegalArgumentException("Reader must not be null");
}
if (reader instanceof BufferedReader) {
bufferedReader = (BufferedReader)reader;
}
else {
bufferedReader = new BufferedReader(reader);
}
}
// -----------------------------------------------------------------------
/**
* Indicates whether the Reader
has more lines. If there is an
* IOException
then {@link #close()} will be called on this instance.
*
* @return true
if the Reader has more lines
* @throws IllegalStateException if an IO exception occurs
*/
public boolean hasNext() {
if (cachedLine != null) {
return true;
}
else if (finished) {
return false;
}
else {
try {
while (true) {
String line = bufferedReader.readLine();
if (line == null) {
finished = true;
return false;
}
else if (isValidLine(line)) {
cachedLine = line;
return true;
}
}
}
catch (IOException ioe) {
close();
throw new IllegalStateException(ioe);
}
}
}
/**
* Overridable method to validate each line that is returned. This implementation always returns
* true.
*
* @param line the line that is to be validated
* @return true if valid, false to remove from the iterator
*/
protected boolean isValidLine(String line) {
return true;
}
/**
* Returns the next line in the wrapped Reader
.
*
* @return the next line from the input
* @throws NoSuchElementException if there is no line to return
*/
public String next() {
return nextLine();
}
/**
* Returns the next line in the wrapped Reader
.
*
* @return the next line from the input
* @throws NoSuchElementException if there is no line to return
*/
public String nextLine() {
if (!hasNext()) {
throw new NoSuchElementException("No more lines");
}
String currentLine = cachedLine;
cachedLine = null;
return currentLine;
}
/**
* Closes the underlying Reader
quietly. This method is useful if you only want to
* process the first few lines of a larger file. If you do not close the iterator then the
* Reader
remains open. This method can safely be called multiple times.
*/
public void close() {
finished = true;
Streams.safeClose(bufferedReader);
cachedLine = null;
}
/**
* Unsupported.
*
* @throws UnsupportedOperationException always
*/
public void remove() {
throw Exceptions.unsupported("Remove unsupported on LineIterator");
}
}