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