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