KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > io > LineNumberReader


1 /*
2  * @(#)LineNumberReader.java 1.20 03/12/19
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.io;
9
10
11 /**
12  * A buffered character-input stream that keeps track of line numbers.
13  * This class defines methods <CODE>void setLineNumber(int)</CODE> and
14  * <CODE>int getLineNumber()</CODE> for setting and getting the current
15  * line number respectively.
16  * <P>
17  * By default, line numbering begins at 0. This number increments as data is
18  * read, and can be changed with a call to <CODE>setLineNumber(int)</CODE>.
19  * Note however, that <CODE>setLineNumber(int)</CODE> does not actually change the current
20  * position in the stream; it only changes the value that will be returned
21  * by <CODE>getLineNumber()</CODE>.
22  * <P>
23  * A line is considered to be terminated by any one of a line feed ('\n'), a carriage
24  * return ('\r'), or a carriage return followed immediately by a linefeed.
25  *
26  * @version 1.20, 03/12/19
27  * @author Mark Reinhold
28  * @since JDK1.1
29  */

30
31 public class LineNumberReader extends BufferedReader JavaDoc {
32
33     /** The current line number */
34     private int lineNumber = 0;
35
36     /** The line number of the mark, if any */
37     private int markedLineNumber; // Defaults to 0
38

39     /** If the next character is a line feed, skip it */
40     private boolean skipLF;
41
42     /** The skipLF flag when the mark was set */
43     private boolean markedSkipLF;
44
45     /**
46      * Create a new line-numbering reader, using the default input-buffer
47      * size.
48      *
49      * @param in a Reader object to provide the underlying stream.
50      */

51     public LineNumberReader(Reader JavaDoc in) {
52     super(in);
53     }
54
55     /**
56      * Create a new line-numbering reader, reading characters into a buffer of
57      * the given size.
58      *
59      * @param in a Reader object to provide the underlying stream.
60      * @param sz an int specifying the size of the buffer.
61      */

62     public LineNumberReader(Reader JavaDoc in, int sz) {
63     super(in, sz);
64     }
65
66     /**
67      * Set the current line number.
68      *
69      * @param lineNumber an int specifying the line number.
70      * @see #getLineNumber
71      */

72     public void setLineNumber(int lineNumber) {
73     this.lineNumber = lineNumber;
74     }
75
76     /**
77      * Get the current line number.
78      *
79      * @return The current line number.
80      * @see #setLineNumber
81      */

82     public int getLineNumber() {
83     return lineNumber;
84     }
85
86     /**
87      * Read a single character. Line terminators are compressed into single
88      * newline ('\n') characters.
89      *
90      * @return The character read, or -1 if the end of the stream has been
91      * reached
92      *
93      * @exception IOException If an I/O error occurs
94      */

95     public int read() throws IOException JavaDoc {
96     synchronized (lock) {
97         int c = super.read();
98         if (skipLF) {
99         if (c == '\n')
100             c = super.read();
101         skipLF = false;
102         }
103         switch (c) {
104         case '\r':
105         skipLF = true;
106         case '\n': /* Fall through */
107         lineNumber++;
108         return '\n';
109         }
110         return c;
111     }
112     }
113
114     /**
115      * Read characters into a portion of an array.
116      *
117      * @param cbuf Destination buffer
118      * @param off Offset at which to start storing characters
119      * @param len Maximum number of characters to read
120      *
121      * @return The number of bytes read, or -1 if the end of the stream has
122      * already been reached
123      *
124      * @exception IOException If an I/O error occurs
125      */

126     public int read(char cbuf[], int off, int len) throws IOException JavaDoc {
127     synchronized (lock) {
128         int n = super.read(cbuf, off, len);
129
130         for (int i = off; i < off + n; i++) {
131         int c = cbuf[i];
132         if (skipLF) {
133             skipLF = false;
134             if (c == '\n')
135             continue;
136         }
137         switch (c) {
138         case '\r':
139             skipLF = true;
140         case '\n': /* Fall through */
141             lineNumber++;
142             break;
143         }
144         }
145
146         return n;
147     }
148     }
149
150     /**
151      * Read a line of text. A line is considered to be terminated by any one
152      * of a line feed ('\n'), a carriage return ('\r'), or a carriage return
153      * followed immediately by a linefeed.
154      *
155      * @return A String containing the contents of the line, not including
156      * any line-termination characters, or null if the end of the
157      * stream has been reached
158      *
159      * @exception IOException If an I/O error occurs
160      */

161     public String JavaDoc readLine() throws IOException JavaDoc {
162     synchronized (lock) {
163         String JavaDoc l = super.readLine(skipLF);
164             skipLF = false;
165         if (l != null)
166         lineNumber++;
167         return l;
168     }
169     }
170
171     /** Maximum skip-buffer size */
172     private static final int maxSkipBufferSize = 8192;
173
174     /** Skip buffer, null until allocated */
175     private char skipBuffer[] = null;
176
177     /**
178      * Skip characters.
179      *
180      * @param n The number of characters to skip
181      *
182      * @return The number of characters actually skipped
183      *
184      * @exception IOException If an I/O error occurs
185      * @exception IllegalArgumentException if <CODE>n</CODE>
186      * is negative
187      */

188     public long skip(long n) throws IOException JavaDoc {
189     if (n < 0)
190         throw new IllegalArgumentException JavaDoc("skip() value is negative");
191     int nn = (int) Math.min(n, maxSkipBufferSize);
192     synchronized (lock) {
193         if ((skipBuffer == null) || (skipBuffer.length < nn))
194         skipBuffer = new char[nn];
195         long r = n;
196         while (r > 0) {
197         int nc = read(skipBuffer, 0, (int) Math.min(r, nn));
198         if (nc == -1)
199             break;
200         r -= nc;
201         }
202         return n - r;
203     }
204     }
205
206     /**
207      * Mark the present position in the stream. Subsequent calls to reset()
208      * will attempt to reposition the stream to this point, and will also reset
209      * the line number appropriately.
210      *
211      * @param readAheadLimit Limit on the number of characters that may be
212      * read while still preserving the mark. After
213      * reading this many characters, attempting to
214      * reset the stream may fail.
215      *
216      * @exception IOException If an I/O error occurs
217      */

218     public void mark(int readAheadLimit) throws IOException JavaDoc {
219     synchronized (lock) {
220         super.mark(readAheadLimit);
221         markedLineNumber = lineNumber;
222             markedSkipLF = skipLF;
223     }
224     }
225
226     /**
227      * Reset the stream to the most recent mark.
228      *
229      * @exception IOException If the stream has not been marked,
230      * or if the mark has been invalidated
231      */

232     public void reset() throws IOException JavaDoc {
233     synchronized (lock) {
234         super.reset();
235         lineNumber = markedLineNumber;
236             skipLF = markedSkipLF;
237     }
238     }
239
240 }
241
Popular Tags