/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.commons.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;

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 close() or closeQuietly(LineIterator) method on the iterator.

The recommended usage pattern is:

LineIterator it = FileUtils.lineIterator(file, "UTF-8");
try {
  while (it.hasNext()) {
    String line = it.nextLine();
    // do something with line
  }
} finally {
  it.close();
}
Since:1.2
/** * An Iterator over the lines in a <code>Reader</code>. * <p> * <code>LineIterator</code> holds a reference to an open <code>Reader</code>. * 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()} or {@link #closeQuietly(LineIterator)} * method on the iterator. * <p> * The recommended usage pattern is: * <pre> * LineIterator it = FileUtils.lineIterator(file, "UTF-8"); * try { * while (it.hasNext()) { * String line = it.nextLine(); * // do something with line * } * } finally { * it.close(); * } * </pre> * * @since 1.2 */
public class LineIterator implements Iterator<String>, Closeable { // N.B. This class deliberately does not implement Iterable, see https://issues.apache.org/jira/browse/IO-181
The reader that is being read.
/** The reader that is being read. */
private final BufferedReader bufferedReader;
The current line.
/** The current line. */
private String cachedLine;
A flag indicating if the iterator has been fully read.
/** A flag indicating if the iterator has been fully read. */
private boolean finished = false;
Constructs an iterator of the lines for a Reader.
Params:
  • reader – the Reader to read from, not null
Throws:
/** * Constructs an iterator of the lines for a <code>Reader</code>. * * @param reader the <code>Reader</code> 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 close() will be called on this instance.
Throws:
Returns:true if the Reader has more lines
/** * Indicates whether the <code>Reader</code> has more lines. * If there is an <code>IOException</code> then {@link #close()} will * be called on this instance. * * @return {@code true} if the Reader has more lines * @throws IllegalStateException if an IO exception occurs */
@Override public boolean hasNext() { if (cachedLine != null) { return true; } else if (finished) { return false; } else { try { while (true) { final String line = bufferedReader.readLine(); if (line == null) { finished = true; return false; } else if (isValidLine(line)) { cachedLine = line; return true; } } } catch(final IOException ioe) { try { close(); } catch (final IOException e) { ioe.addSuppressed(e); } throw new IllegalStateException(ioe); } } }
Overridable method to validate each line that is returned. This implementation always returns true.
Params:
  • line – the line that is to be validated
Returns:true if valid, false to remove from the iterator
/** * 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(final String line) { return true; }
Returns the next line in the wrapped Reader.
Throws:
Returns:the next line from the input
/** * Returns the next line in the wrapped <code>Reader</code>. * * @return the next line from the input * @throws NoSuchElementException if there is no line to return */
@Override public String next() { return nextLine(); }
Returns the next line in the wrapped Reader.
Throws:
Returns:the next line from the input
/** * Returns the next line in the wrapped <code>Reader</code>. * * @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"); } final String currentLine = cachedLine; cachedLine = null; return currentLine; }
Closes the underlying Reader. 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.
Throws:
  • IOException – if closing the underlying Reader fails.
/** * Closes the underlying {@code Reader}. * 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 {@code Reader} remains open. * This method can safely be called multiple times. * * @throws IOException if closing the underlying {@code Reader} fails. */
@Override public void close() throws IOException { finished = true; cachedLine = null; if (this.bufferedReader != null) { this.bufferedReader.close(); } }
Unsupported.
Throws:
  • UnsupportedOperationException – always
/** * Unsupported. * * @throws UnsupportedOperationException always */
@Override public void remove() { throw new UnsupportedOperationException("Remove unsupported on LineIterator"); } //-----------------------------------------------------------------------
Closes a LineIterator quietly.
Params:
  • iterator – The iterator to close, or null.
See Also:
Deprecated:As of 2.6 removed without replacement. Please use the try-with-resources statement or handle suppressed exceptions manually.
/** * Closes a {@code LineIterator} quietly. * * @param iterator The iterator to close, or {@code null}. * @deprecated As of 2.6 removed without replacement. Please use the try-with-resources statement or handle * suppressed exceptions manually. * @see Throwable#addSuppressed(java.lang.Throwable) */
@Deprecated public static void closeQuietly(final LineIterator iterator) { try { if (iterator != null) { iterator.close(); } } catch(final IOException e) { // Suppressed. } } }