1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package net.sf.statcvs.util;
24
25 import java.io.BufferedReader;
26 import java.io.IOException;
27 import java.io.Reader;
28 import java.util.NoSuchElementException;
29
30 /**
31 * <p>Wraps a {@link java.io.Reader} for line-by-line access.
32 * This works like {@link java.util.Iterator}: {@link #hasNextLine}
33 * returns true if another line can be read; {@link #nextLine} reads
34 * the next line and returns it. Additionally, {@link #getCurrentLine}
35 * can be used to access multiple times the line returned by
36 * <tt>nextLine()</tt>.</p>
37 *
38 * <p>At construction time, <tt>getCurrentLine()</tt> is undefined.
39 * <tt>nextLine()</tt> must be called once to read the first line.</p>
40 *
41 * @author Richard Cyganiak (richard@cyganiak.de)
42 * @version $Id: LookaheadReader.java,v 1.4 2008/04/02 11:22:15 benoitx Exp $
43 */
44 public class LookaheadReader {
45 private final BufferedReader reader;
46 private String currentLine = null;
47 private String nextLine = null;
48 private boolean afterEnd = false;
49 private int lineNumber = 0;
50
51 /**
52 * Creates a LookaheadReader from a source reader.
53 * @param reader a reader whose contents will be returned by the
54 * LookaheadReader
55 */
56 public LookaheadReader(final Reader reader) {
57 this.reader = new BufferedReader(reader);
58 }
59
60 /**
61 * Returns the current line without reading a line from the source
62 * reader. Will throw an exception if {@link #nextLine} was not
63 * called before.
64 * @return The line returned by the previous call to {@link #nextLine()}
65 * @throws NoSuchElementException if {@link #nextLine} was not yet called
66 */
67 public String getCurrentLine() {
68 if (this.currentLine == null) {
69 throw new NoSuchElementException("Call to getCurrentLine() before nextLine() was called");
70 }
71 return this.currentLine;
72 }
73
74 /**
75 * Reads and returns a line from the source reader. The result of
76 * this call will be the new current line. Will throw an exception
77 * if trying to read from after the end of the source reader.
78 * @return The next line of the source reader
79 * @throws IOException on error while reading the source reader
80 * @throws NoSuchElementException if {@link #hasNextLine} is false
81 */
82 public String nextLine() throws IOException {
83 if (!hasNextLine()) {
84 throw new NoSuchElementException("Call to nextLine() when hasNextLine() is false");
85 }
86 this.currentLine = this.nextLine;
87 this.nextLine = null;
88 this.lineNumber++;
89 return this.currentLine;
90 }
91
92 /**
93 * Checks if more lines are available for reading.
94 * @return <tt>true</tt> if at least one more line can be read
95 * @throws IOException on error while reading the source reader
96 */
97 public boolean hasNextLine() throws IOException {
98 if (this.afterEnd) {
99 return false;
100 }
101 if (this.nextLine != null) {
102 return true;
103 }
104 this.nextLine = this.reader.readLine();
105 if (this.nextLine != null) {
106 return true;
107 }
108 this.afterEnd = true;
109 return false;
110 }
111
112 /**
113 * Returns the number of the line that would be returned by
114 * {@link #getCurrentLine}, or 0 before the first
115 * call to {@link #nextLine}. The first line has line number 1.
116 * @return the current line number
117 */
118 public int getLineNumber() {
119 return this.lineNumber;
120 }
121 }