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.
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.
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).
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.
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
28 import org.apidesign.bck2brwsr.emul.lang.System;
32 * Reads text from a character-input stream, buffering characters so as to
33 * provide for the efficient reading of characters, arrays, and lines.
35 * <p> The buffer size may be specified, or the default size may be used. The
36 * default is large enough for most purposes.
38 * <p> In general, each read request made of a Reader causes a corresponding
39 * read request to be made of the underlying character or byte stream. It is
40 * therefore advisable to wrap a BufferedReader around any Reader whose read()
41 * operations may be costly, such as FileReaders and InputStreamReaders. For
46 * = new BufferedReader(new FileReader("foo.in"));
49 * will buffer the input from the specified file. Without buffering, each
50 * invocation of read() or readLine() could cause bytes to be read from the
51 * file, converted into characters, and then returned, which can be very
54 * <p> Programs that use DataInputStreams for textual input can be localized by
55 * replacing each DataInputStream with an appropriate BufferedReader.
58 * @see InputStreamReader
59 * @see java.nio.file.Files#newBufferedReader
61 * @author Mark Reinhold
65 public class BufferedReader extends Reader {
70 private int nChars, nextChar;
72 private static final int INVALIDATED = -2;
73 private static final int UNMARKED = -1;
74 private int markedChar = UNMARKED;
75 private int readAheadLimit = 0; /* Valid only when markedChar > 0 */
77 /** If the next character is a line feed, skip it */
78 private boolean skipLF = false;
80 /** The skipLF flag when the mark was set */
81 private boolean markedSkipLF = false;
83 private static int defaultCharBufferSize = 8192;
84 private static int defaultExpectedLineLength = 80;
87 * Creates a buffering character-input stream that uses an input buffer of
91 * @param sz Input-buffer size
93 * @exception IllegalArgumentException If sz is <= 0
95 public BufferedReader(Reader in, int sz) {
98 throw new IllegalArgumentException("Buffer size <= 0");
101 nextChar = nChars = 0;
105 * Creates a buffering character-input stream that uses a default-sized
110 public BufferedReader(Reader in) {
111 this(in, defaultCharBufferSize);
114 /** Checks to make sure that the stream has not been closed */
115 private void ensureOpen() throws IOException {
117 throw new IOException("Stream closed");
121 * Fills the input buffer, taking the mark into account if it is valid.
123 private void fill() throws IOException {
125 if (markedChar <= UNMARKED) {
130 int delta = nextChar - markedChar;
131 if (delta >= readAheadLimit) {
132 /* Gone past read-ahead limit: Invalidate mark */
133 markedChar = INVALIDATED;
137 if (readAheadLimit <= cb.length) {
138 /* Shuffle in the current buffer */
139 System.arraycopy(cb, markedChar, cb, 0, delta);
143 /* Reallocate buffer to accommodate read-ahead limit */
144 char ncb[] = new char[readAheadLimit];
145 System.arraycopy(cb, markedChar, ncb, 0, delta);
150 nextChar = nChars = delta;
156 n = in.read(cb, dst, cb.length - dst);
165 * Reads a single character.
167 * @return The character read, as an integer in the range
168 * 0 to 65535 (<tt>0x00-0xffff</tt>), or -1 if the
169 * end of the stream has been reached
170 * @exception IOException If an I/O error occurs
172 public int read() throws IOException {
173 synchronized (lock) {
176 if (nextChar >= nChars) {
178 if (nextChar >= nChars)
183 if (cb[nextChar] == '\n') {
188 return cb[nextChar++];
194 * Reads characters into a portion of an array, reading from the underlying
195 * stream if necessary.
197 private int read1(char[] cbuf, int off, int len) throws IOException {
198 if (nextChar >= nChars) {
199 /* If the requested length is at least as large as the buffer, and
200 if there is no mark/reset activity, and if line feeds are not
201 being skipped, do not bother to copy the characters into the
202 local buffer. In this way buffered streams will cascade
204 if (len >= cb.length && markedChar <= UNMARKED && !skipLF) {
205 return in.read(cbuf, off, len);
209 if (nextChar >= nChars) return -1;
212 if (cb[nextChar] == '\n') {
214 if (nextChar >= nChars)
216 if (nextChar >= nChars)
220 int n = Math.min(len, nChars - nextChar);
221 System.arraycopy(cb, nextChar, cbuf, off, n);
227 * Reads characters into a portion of an array.
229 * <p> This method implements the general contract of the corresponding
230 * <code>{@link Reader#read(char[], int, int) read}</code> method of the
231 * <code>{@link Reader}</code> class. As an additional convenience, it
232 * attempts to read as many characters as possible by repeatedly invoking
233 * the <code>read</code> method of the underlying stream. This iterated
234 * <code>read</code> continues until one of the following conditions becomes
237 * <li> The specified number of characters have been read,
239 * <li> The <code>read</code> method of the underlying stream returns
240 * <code>-1</code>, indicating end-of-file, or
242 * <li> The <code>ready</code> method of the underlying stream
243 * returns <code>false</code>, indicating that further input requests
246 * </ul> If the first <code>read</code> on the underlying stream returns
247 * <code>-1</code> to indicate end-of-file then this method returns
248 * <code>-1</code>. Otherwise this method returns the number of characters
251 * <p> Subclasses of this class are encouraged, but not required, to
252 * attempt to read as many characters as possible in the same fashion.
254 * <p> Ordinarily this method takes characters from this stream's character
255 * buffer, filling it from the underlying stream as necessary. If,
256 * however, the buffer is empty, the mark is not valid, and the requested
257 * length is at least as large as the buffer, then this method will read
258 * characters directly from the underlying stream into the given array.
259 * Thus redundant <code>BufferedReader</code>s will not copy data
262 * @param cbuf Destination buffer
263 * @param off Offset at which to start storing characters
264 * @param len Maximum number of characters to read
266 * @return The number of characters read, or -1 if the end of the
267 * stream has been reached
269 * @exception IOException If an I/O error occurs
271 public int read(char cbuf[], int off, int len) throws IOException {
272 synchronized (lock) {
274 if ((off < 0) || (off > cbuf.length) || (len < 0) ||
275 ((off + len) > cbuf.length) || ((off + len) < 0)) {
276 throw new IndexOutOfBoundsException();
277 } else if (len == 0) {
281 int n = read1(cbuf, off, len);
282 if (n <= 0) return n;
283 while ((n < len) && in.ready()) {
284 int n1 = read1(cbuf, off + n, len - n);
293 * Reads a line of text. A line is considered to be terminated by any one
294 * of a line feed ('\n'), a carriage return ('\r'), or a carriage return
295 * followed immediately by a linefeed.
297 * @param ignoreLF If true, the next '\n' will be skipped
299 * @return A String containing the contents of the line, not including
300 * any line-termination characters, or null if the end of the
301 * stream has been reached
303 * @see java.io.LineNumberReader#readLine()
305 * @exception IOException If an I/O error occurs
307 String readLine(boolean ignoreLF) throws IOException {
308 StringBuffer s = null;
311 synchronized (lock) {
313 boolean omitLF = ignoreLF || skipLF;
318 if (nextChar >= nChars)
320 if (nextChar >= nChars) { /* EOF */
321 if (s != null && s.length() > 0)
330 /* Skip a leftover '\n', if necessary */
331 if (omitLF && (cb[nextChar] == '\n'))
337 for (i = nextChar; i < nChars; i++) {
339 if ((c == '\n') || (c == '\r')) {
345 startChar = nextChar;
351 str = new String(cb, startChar, i - startChar);
353 s.append(cb, startChar, i - startChar);
364 s = new StringBuffer(defaultExpectedLineLength);
365 s.append(cb, startChar, i - startChar);
371 * Reads a line of text. A line is considered to be terminated by any one
372 * of a line feed ('\n'), a carriage return ('\r'), or a carriage return
373 * followed immediately by a linefeed.
375 * @return A String containing the contents of the line, not including
376 * any line-termination characters, or null if the end of the
377 * stream has been reached
379 * @exception IOException If an I/O error occurs
381 * @see java.nio.file.Files#readAllLines
383 public String readLine() throws IOException {
384 return readLine(false);
390 * @param n The number of characters to skip
392 * @return The number of characters actually skipped
394 * @exception IllegalArgumentException If <code>n</code> is negative.
395 * @exception IOException If an I/O error occurs
397 public long skip(long n) throws IOException {
399 throw new IllegalArgumentException("skip value is negative");
401 synchronized (lock) {
405 if (nextChar >= nChars)
407 if (nextChar >= nChars) /* EOF */
411 if (cb[nextChar] == '\n') {
415 long d = nChars - nextChar;
431 * Tells whether this stream is ready to be read. A buffered character
432 * stream is ready if the buffer is not empty, or if the underlying
433 * character stream is ready.
435 * @exception IOException If an I/O error occurs
437 public boolean ready() throws IOException {
438 synchronized (lock) {
442 * If newline needs to be skipped and the next char to be read
443 * is a newline character, then just skip it right away.
446 /* Note that in.ready() will return true if and only if the next
447 * read on the stream will not block.
449 if (nextChar >= nChars && in.ready()) {
452 if (nextChar < nChars) {
453 if (cb[nextChar] == '\n')
458 return (nextChar < nChars) || in.ready();
463 * Tells whether this stream supports the mark() operation, which it does.
465 public boolean markSupported() {
470 * Marks the present position in the stream. Subsequent calls to reset()
471 * will attempt to reposition the stream to this point.
473 * @param readAheadLimit Limit on the number of characters that may be
474 * read while still preserving the mark. An attempt
475 * to reset the stream after reading characters
476 * up to this limit or beyond may fail.
477 * A limit value larger than the size of the input
478 * buffer will cause a new buffer to be allocated
479 * whose size is no smaller than limit.
480 * Therefore large values should be used with care.
482 * @exception IllegalArgumentException If readAheadLimit is < 0
483 * @exception IOException If an I/O error occurs
485 public void mark(int readAheadLimit) throws IOException {
486 if (readAheadLimit < 0) {
487 throw new IllegalArgumentException("Read-ahead limit < 0");
489 synchronized (lock) {
491 this.readAheadLimit = readAheadLimit;
492 markedChar = nextChar;
493 markedSkipLF = skipLF;
498 * Resets the stream to the most recent mark.
500 * @exception IOException If the stream has never been marked,
501 * or if the mark has been invalidated
503 public void reset() throws IOException {
504 synchronized (lock) {
507 throw new IOException((markedChar == INVALIDATED)
509 : "Stream not marked");
510 nextChar = markedChar;
511 skipLF = markedSkipLF;
515 public void close() throws IOException {
516 synchronized (lock) {