Coverage Report - org.apache.commons.io.LineIterator
 
Classes in this File Line Coverage Branch Coverage Complexity
LineIterator
97%
38/39
100%
16/16
3.25
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to You under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  You may obtain a copy of the License at
 8  
  *
 9  
  *      http://www.apache.org/licenses/LICENSE-2.0
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 package org.apache.commons.io;
 18  
 
 19  
 import java.io.BufferedReader;
 20  
 import java.io.IOException;
 21  
 import java.io.Reader;
 22  
 import java.util.Iterator;
 23  
 import java.util.NoSuchElementException;
 24  
 
 25  
 /**
 26  
  * An Iterator over the lines in a <code>Reader</code>.
 27  
  * <p>
 28  
  * <code>LineIterator</code> holds a reference to an open <code>Reader</code>.
 29  
  * When you have finished with the iterator you should close the reader
 30  
  * to free internal resources. This can be done by closing the reader directly,
 31  
  * or by calling the {@link #close()} or {@link #closeQuietly(LineIterator)}
 32  
  * method on the iterator.
 33  
  * <p>
 34  
  * The recommended usage pattern is:
 35  
  * <pre>
 36  
  * LineIterator it = FileUtils.lineIterator(file, "UTF-8");
 37  
  * try {
 38  
  *   while (it.hasNext()) {
 39  
  *     String line = it.nextLine();
 40  
  *     // do something with line
 41  
  *   }
 42  
  * } finally {
 43  
  *   it.close();
 44  
  * }
 45  
  * </pre>
 46  
  *
 47  
  * @version $Id: LineIterator.java 1471767 2013-04-24 23:24:19Z sebb $
 48  
  * @since 1.2
 49  
  */
 50  0
 public class LineIterator implements Iterator<String> {
 51  
 
 52  
     // N.B. This class deliberately does not implement Iterable, see https://issues.apache.org/jira/browse/IO-181
 53  
 
 54  
     /** The reader that is being read. */
 55  
     private final BufferedReader bufferedReader;
 56  
     /** The current line. */
 57  
     private String cachedLine;
 58  
     /** A flag indicating if the iterator has been fully read. */
 59  28
     private boolean finished = false;
 60  
 
 61  
     /**
 62  
      * Constructs an iterator of the lines for a <code>Reader</code>.
 63  
      *
 64  
      * @param reader the <code>Reader</code> to read from, not null
 65  
      * @throws IllegalArgumentException if the reader is null
 66  
      */
 67  28
     public LineIterator(final Reader reader) throws IllegalArgumentException {
 68  28
         if (reader == null) {
 69  2
             throw new IllegalArgumentException("Reader must not be null");
 70  
         }
 71  26
         if (reader instanceof BufferedReader) {
 72  4
             bufferedReader = (BufferedReader) reader;
 73  
         } else {
 74  22
             bufferedReader = new BufferedReader(reader);
 75  
         }
 76  26
     }
 77  
 
 78  
     //-----------------------------------------------------------------------
 79  
     /**
 80  
      * Indicates whether the <code>Reader</code> has more lines.
 81  
      * If there is an <code>IOException</code> then {@link #close()} will
 82  
      * be called on this instance.
 83  
      *
 84  
      * @return {@code true} if the Reader has more lines
 85  
      * @throws IllegalStateException if an IO exception occurs
 86  
      */
 87  
     public boolean hasNext() {
 88  170
         if (cachedLine != null) {
 89  42
             return true;
 90  128
         } else if (finished) {
 91  34
             return false;
 92  
         } else {
 93  
             try {
 94  
                 while (true) {
 95  106
                     final String line = bufferedReader.readLine();
 96  104
                     if (line == null) {
 97  22
                         finished = true;
 98  22
                         return false;
 99  82
                     } else if (isValidLine(line)) {
 100  70
                         cachedLine = line;
 101  70
                         return true;
 102  
                     }
 103  12
                 }
 104  2
             } catch(final IOException ioe) {
 105  2
                 close();
 106  2
                 throw new IllegalStateException(ioe);
 107  
             }
 108  
         }
 109  
     }
 110  
 
 111  
     /**
 112  
      * Overridable method to validate each line that is returned.
 113  
      * This implementation always returns true.
 114  
      * @param line  the line that is to be validated
 115  
      * @return true if valid, false to remove from the iterator
 116  
      */
 117  
     protected boolean isValidLine(final String line) {
 118  46
         return true;
 119  
     }
 120  
 
 121  
     /**
 122  
      * Returns the next line in the wrapped <code>Reader</code>.
 123  
      *
 124  
      * @return the next line from the input
 125  
      * @throws NoSuchElementException if there is no line to return
 126  
      */
 127  
     public String next() {
 128  66
         return nextLine();
 129  
     }
 130  
 
 131  
     /**
 132  
      * Returns the next line in the wrapped <code>Reader</code>.
 133  
      *
 134  
      * @return the next line from the input
 135  
      * @throws NoSuchElementException if there is no line to return
 136  
      */
 137  
     public String nextLine() {
 138  100
         if (!hasNext()) {
 139  32
             throw new NoSuchElementException("No more lines");
 140  
         }
 141  68
         final String currentLine = cachedLine;
 142  68
         cachedLine = null;
 143  68
         return currentLine;
 144  
     }
 145  
 
 146  
     /**
 147  
      * Closes the underlying <code>Reader</code> quietly.
 148  
      * This method is useful if you only want to process the first few
 149  
      * lines of a larger file. If you do not close the iterator
 150  
      * then the <code>Reader</code> remains open.
 151  
      * This method can safely be called multiple times.
 152  
      */
 153  
     public void close() {
 154  30
         finished = true;
 155  30
         IOUtils.closeQuietly(bufferedReader);
 156  30
         cachedLine = null;
 157  30
     }
 158  
 
 159  
     /**
 160  
      * Unsupported.
 161  
      *
 162  
      * @throws UnsupportedOperationException always
 163  
      */
 164  
     public void remove() {
 165  12
         throw new UnsupportedOperationException("Remove unsupported on LineIterator");
 166  
     }
 167  
 
 168  
     //-----------------------------------------------------------------------
 169  
     /**
 170  
      * Closes the iterator, handling null and ignoring exceptions.
 171  
      *
 172  
      * @param iterator  the iterator to close
 173  
      */
 174  
     public static void closeQuietly(final LineIterator iterator) {
 175  28
         if (iterator != null) {
 176  24
             iterator.close();
 177  
         }
 178  28
     }
 179  
 
 180  
 }