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 try { 518 in.close(); 519 } finally { 520 in = null; 521 cb = null; 522 } 523 } 524 } 525 }