1 /*
2 * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.io;
27
28
29 /**
30 * Reads text from a character-input stream, buffering characters so as to
31 * provide for the efficient reading of characters, arrays, and lines.
32 *
33 * <p> The buffer size may be specified, or the default size may be used. The
34 * default is large enough for most purposes.
35 *
36 * <p> In general, each read request made of a Reader causes a corresponding
37 * read request to be made of the underlying character or byte stream. It is
38 * therefore advisable to wrap a BufferedReader around any Reader whose read()
39 * operations may be costly, such as FileReaders and InputStreamReaders. For
40 * example,
41 *
42 * <pre>
43 * BufferedReader in
44 * = new BufferedReader(new FileReader("foo.in"));
45 * </pre>
46 *
47 * will buffer the input from the specified file. Without buffering, each
48 * invocation of read() or readLine() could cause bytes to be read from the
49 * file, converted into characters, and then returned, which can be very
50 * inefficient.
51 *
52 * <p> Programs that use DataInputStreams for textual input can be localized by
53 * replacing each DataInputStream with an appropriate BufferedReader.
54 *
55 * @see FileReader
56 * @see InputStreamReader
57 * @see java.nio.file.Files#newBufferedReader
58 *
59 * @author Mark Reinhold
60 * @since JDK1.1
61 */
62
63 public class BufferedReader extends Reader {
64
65 private Reader in;
66
67 private char cb[];
68 private int nChars, nextChar;
69
70 private static final int INVALIDATED = -2;
71 private static final int UNMARKED = -1;
72 private int markedChar = UNMARKED;
73 private int readAheadLimit = 0; /* Valid only when markedChar > 0 */
74
75 /** If the next character is a line feed, skip it */
76 private boolean skipLF = false;
77
78 /** The skipLF flag when the mark was set */
79 private boolean markedSkipLF = false;
80
81 private static int defaultCharBufferSize = 8192;
82 private static int defaultExpectedLineLength = 80;
83
84 /**
85 * Creates a buffering character-input stream that uses an input buffer of
86 * the specified size.
87 *
88 * @param in A Reader
89 * @param sz Input-buffer size
90 *
91 * @exception IllegalArgumentException If sz is <= 0
92 */
93 public BufferedReader(Reader in, int sz) {
94 super(in);
95 if (sz <= 0)
96 throw new IllegalArgumentException("Buffer size <= 0");
97 this.in = in;
98 cb = new char[sz];
99 nextChar = nChars = 0;
100 }
101
102 /**
103 * Creates a buffering character-input stream that uses a default-sized
104 * input buffer.
105 *
106 * @param in A Reader
107 */
108 public BufferedReader(Reader in) {
109 this(in, defaultCharBufferSize);
110 }
111
112 /** Checks to make sure that the stream has not been closed */
113 private void ensureOpen() throws IOException {
114 if (in == null)
115 throw new IOException("Stream closed");
116 }
117
118 /**
119 * Fills the input buffer, taking the mark into account if it is valid.
120 */
121 private void fill() throws IOException {
122 int dst;
123 if (markedChar <= UNMARKED) {
124 /* No mark */
125 dst = 0;
126 } else {
127 /* Marked */
128 int delta = nextChar - markedChar;
129 if (delta >= readAheadLimit) {
130 /* Gone past read-ahead limit: Invalidate mark */
131 markedChar = INVALIDATED;
132 readAheadLimit = 0;
133 dst = 0;
134 } else {
135 if (readAheadLimit <= cb.length) {
136 /* Shuffle in the current buffer */
137 System.arraycopy(cb, markedChar, cb, 0, delta);
138 markedChar = 0;
139 dst = delta;
140 } else {
141 /* Reallocate buffer to accommodate read-ahead limit */
142 char ncb[] = new char[readAheadLimit];
143 System.arraycopy(cb, markedChar, ncb, 0, delta);
144 cb = ncb;
145 markedChar = 0;
146 dst = delta;
147 }
148 nextChar = nChars = delta;
149 }
150 }
151
152 int n;
153 do {
154 n = in.read(cb, dst, cb.length - dst);
155 } while (n == 0);
156 if (n > 0) {
157 nChars = dst + n;
158 nextChar = dst;
159 }
160 }
161
162 /**
163 * Reads a single character.
164 *
165 * @return The character read, as an integer in the range
166 * 0 to 65535 (<tt>0x00-0xffff</tt>), or -1 if the
167 * end of the stream has been reached
168 * @exception IOException If an I/O error occurs
169 */
170 public int read() throws IOException {
171 synchronized (lock) {
172 ensureOpen();
173 for (;;) {
174 if (nextChar >= nChars) {
175 fill();
176 if (nextChar >= nChars)
177 return -1;
178 }
179 if (skipLF) {
180 skipLF = false;
181 if (cb[nextChar] == '\n') {
182 nextChar++;
183 continue;
184 }
185 }
186 return cb[nextChar++];
187 }
188 }
189 }
190
191 /**
192 * Reads characters into a portion of an array, reading from the underlying
193 * stream if necessary.
194 */
195 private int read1(char[] cbuf, int off, int len) throws IOException {
196 if (nextChar >= nChars) {
197 /* If the requested length is at least as large as the buffer, and
198 if there is no mark/reset activity, and if line feeds are not
199 being skipped, do not bother to copy the characters into the
200 local buffer. In this way buffered streams will cascade
201 harmlessly. */
202 if (len >= cb.length && markedChar <= UNMARKED && !skipLF) {
203 return in.read(cbuf, off, len);
204 }
205 fill();
206 }
207 if (nextChar >= nChars) return -1;
208 if (skipLF) {
209 skipLF = false;
210 if (cb[nextChar] == '\n') {
211 nextChar++;
212 if (nextChar >= nChars)
213 fill();
214 if (nextChar >= nChars)
215 return -1;
216 }
217 }
218 int n = Math.min(len, nChars - nextChar);
219 System.arraycopy(cb, nextChar, cbuf, off, n);
220 nextChar += n;
221 return n;
222 }
223
224 /**
225 * Reads characters into a portion of an array.
226 *
227 * <p> This method implements the general contract of the corresponding
228 * <code>{@link Reader#read(char[], int, int) read}</code> method of the
229 * <code>{@link Reader}</code> class. As an additional convenience, it
230 * attempts to read as many characters as possible by repeatedly invoking
231 * the <code>read</code> method of the underlying stream. This iterated
232 * <code>read</code> continues until one of the following conditions becomes
233 * true: <ul>
234 *
235 * <li> The specified number of characters have been read,
236 *
237 * <li> The <code>read</code> method of the underlying stream returns
238 * <code>-1</code>, indicating end-of-file, or
239 *
240 * <li> The <code>ready</code> method of the underlying stream
241 * returns <code>false</code>, indicating that further input requests
242 * would block.
243 *
244 * </ul> If the first <code>read</code> on the underlying stream returns
245 * <code>-1</code> to indicate end-of-file then this method returns
246 * <code>-1</code>. Otherwise this method returns the number of characters
247 * actually read.
248 *
249 * <p> Subclasses of this class are encouraged, but not required, to
250 * attempt to read as many characters as possible in the same fashion.
251 *
252 * <p> Ordinarily this method takes characters from this stream's character
253 * buffer, filling it from the underlying stream as necessary. If,
254 * however, the buffer is empty, the mark is not valid, and the requested
255 * length is at least as large as the buffer, then this method will read
256 * characters directly from the underlying stream into the given array.
257 * Thus redundant <code>BufferedReader</code>s will not copy data
258 * unnecessarily.
259 *
260 * @param cbuf Destination buffer
261 * @param off Offset at which to start storing characters
262 * @param len Maximum number of characters to read
263 *
264 * @return The number of characters read, or -1 if the end of the
265 * stream has been reached
266 *
267 * @exception IOException If an I/O error occurs
268 */
269 public int read(char cbuf[], int off, int len) throws IOException {
270 synchronized (lock) {
271 ensureOpen();
272 if ((off < 0) || (off > cbuf.length) || (len < 0) ||
273 ((off + len) > cbuf.length) || ((off + len) < 0)) {
274 throw new IndexOutOfBoundsException();
275 } else if (len == 0) {
276 return 0;
277 }
278
279 int n = read1(cbuf, off, len);
280 if (n <= 0) return n;
281 while ((n < len) && in.ready()) {
282 int n1 = read1(cbuf, off + n, len - n);
283 if (n1 <= 0) break;
284 n += n1;
285 }
286 return n;
287 }
288 }
289
290 /**
291 * Reads a line of text. A line is considered to be terminated by any one
292 * of a line feed ('\n'), a carriage return ('\r'), or a carriage return
293 * followed immediately by a linefeed.
294 *
295 * @param ignoreLF If true, the next '\n' will be skipped
296 *
297 * @return A String containing the contents of the line, not including
298 * any line-termination characters, or null if the end of the
299 * stream has been reached
300 *
301 * @see java.io.LineNumberReader#readLine()
302 *
303 * @exception IOException If an I/O error occurs
304 */
305 String readLine(boolean ignoreLF) throws IOException {
306 StringBuffer s = null;
307 int startChar;
308
309 synchronized (lock) {
310 ensureOpen();
311 boolean omitLF = ignoreLF || skipLF;
312
313 bufferLoop:
314 for (;;) {
315
316 if (nextChar >= nChars)
317 fill();
318 if (nextChar >= nChars) { /* EOF */
319 if (s != null && s.length() > 0)
320 return s.toString();
321 else
322 return null;
323 }
324 boolean eol = false;
325 char c = 0;
326 int i;
327
328 /* Skip a leftover '\n', if necessary */
329 if (omitLF && (cb[nextChar] == '\n'))
330 nextChar++;
331 skipLF = false;
332 omitLF = false;
333
334 charLoop:
335 for (i = nextChar; i < nChars; i++) {
336 c = cb[i];
337 if ((c == '\n') || (c == '\r')) {
338 eol = true;
339 break charLoop;
340 }
341 }
342
343 startChar = nextChar;
344 nextChar = i;
345
346 if (eol) {
347 String str;
348 if (s == null) {
349 str = new String(cb, startChar, i - startChar);
350 } else {
351 s.append(cb, startChar, i - startChar);
352 str = s.toString();
353 }
354 nextChar++;
355 if (c == '\r') {
356 skipLF = true;
357 }
358 return str;
359 }
360
361 if (s == null)
362 s = new StringBuffer(defaultExpectedLineLength);
363 s.append(cb, startChar, i - startChar);
364 }
365 }
366 }
367
368 /**
369 * Reads a line of text. A line is considered to be terminated by any one
370 * of a line feed ('\n'), a carriage return ('\r'), or a carriage return
371 * followed immediately by a linefeed.
372 *
373 * @return A String containing the contents of the line, not including
374 * any line-termination characters, or null if the end of the
375 * stream has been reached
376 *
377 * @exception IOException If an I/O error occurs
378 *
379 * @see java.nio.file.Files#readAllLines
380 */
381 public String readLine() throws IOException {
382 return readLine(false);
383 }
384
385 /**
386 * Skips characters.
387 *
388 * @param n The number of characters to skip
389 *
390 * @return The number of characters actually skipped
391 *
392 * @exception IllegalArgumentException If <code>n</code> is negative.
393 * @exception IOException If an I/O error occurs
394 */
395 public long skip(long n) throws IOException {
396 if (n < 0L) {
397 throw new IllegalArgumentException("skip value is negative");
398 }
399 synchronized (lock) {
400 ensureOpen();
401 long r = n;
402 while (r > 0) {
403 if (nextChar >= nChars)
404 fill();
405 if (nextChar >= nChars) /* EOF */
406 break;
407 if (skipLF) {
408 skipLF = false;
409 if (cb[nextChar] == '\n') {
410 nextChar++;
411 }
412 }
413 long d = nChars - nextChar;
414 if (r <= d) {
415 nextChar += r;
416 r = 0;
417 break;
418 }
419 else {
420 r -= d;
421 nextChar = nChars;
422 }
423 }
424 return n - r;
425 }
426 }
427
428 /**
429 * Tells whether this stream is ready to be read. A buffered character
430 * stream is ready if the buffer is not empty, or if the underlying
431 * character stream is ready.
432 *
433 * @exception IOException If an I/O error occurs
434 */
435 public boolean ready() throws IOException {
436 synchronized (lock) {
437 ensureOpen();
438
439 /*
440 * If newline needs to be skipped and the next char to be read
441 * is a newline character, then just skip it right away.
442 */
443 if (skipLF) {
444 /* Note that in.ready() will return true if and only if the next
445 * read on the stream will not block.
446 */
447 if (nextChar >= nChars && in.ready()) {
448 fill();
449 }
450 if (nextChar < nChars) {
451 if (cb[nextChar] == '\n')
452 nextChar++;
453 skipLF = false;
454 }
455 }
456 return (nextChar < nChars) || in.ready();
457 }
458 }
459
460 /**
461 * Tells whether this stream supports the mark() operation, which it does.
462 */
463 public boolean markSupported() {
464 return true;
465 }
466
467 /**
468 * Marks the present position in the stream. Subsequent calls to reset()
469 * will attempt to reposition the stream to this point.
470 *
471 * @param readAheadLimit Limit on the number of characters that may be
472 * read while still preserving the mark. An attempt
473 * to reset the stream after reading characters
474 * up to this limit or beyond may fail.
475 * A limit value larger than the size of the input
476 * buffer will cause a new buffer to be allocated
477 * whose size is no smaller than limit.
478 * Therefore large values should be used with care.
479 *
480 * @exception IllegalArgumentException If readAheadLimit is < 0
481 * @exception IOException If an I/O error occurs
482 */
483 public void mark(int readAheadLimit) throws IOException {
484 if (readAheadLimit < 0) {
485 throw new IllegalArgumentException("Read-ahead limit < 0");
486 }
487 synchronized (lock) {
488 ensureOpen();
489 this.readAheadLimit = readAheadLimit;
490 markedChar = nextChar;
491 markedSkipLF = skipLF;
492 }
493 }
494
495 /**
496 * Resets the stream to the most recent mark.
497 *
498 * @exception IOException If the stream has never been marked,
499 * or if the mark has been invalidated
500 */
501 public void reset() throws IOException {
502 synchronized (lock) {
503 ensureOpen();
504 if (markedChar < 0)
505 throw new IOException((markedChar == INVALIDATED)
506 ? "Mark invalid"
507 : "Stream not marked");
508 nextChar = markedChar;
509 skipLF = markedSkipLF;
510 }
511 }
512
513 public void close() throws IOException {
514 synchronized (lock) {
515 if (in == null)
516 return;
517 in.close();
518 in = null;
519 cb = null;
520 }
521 }
522 }