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