Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/java/io/BufferedReader.java
38829 views
1
/*
2
* Copyright (c) 1996, 2013, 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 JDK1.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
* @exception 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 (<tt>0x00-0xffff</tt>), or -1 if the
174
* end of the stream has been reached
175
* @exception 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</code> method of the underlying stream. This iterated
239
* <code>read</code> 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</code> method of the underlying stream returns
245
* <code>-1</code>, indicating end-of-file, or
246
*
247
* <li> The <code>ready</code> method of the underlying stream
248
* returns <code>false</code>, indicating that further input requests
249
* would block.
250
*
251
* </ul> If the first <code>read</code> on the underlying stream returns
252
* <code>-1</code> to indicate end-of-file then this method returns
253
* <code>-1</code>. 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</code>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
* @exception IOException If an I/O error occurs
275
*/
276
public int read(char cbuf[], int off, int len) throws IOException {
277
synchronized (lock) {
278
ensureOpen();
279
if ((off < 0) || (off > cbuf.length) || (len < 0) ||
280
((off + len) > cbuf.length) || ((off + len) < 0)) {
281
throw new IndexOutOfBoundsException();
282
} else if (len == 0) {
283
return 0;
284
}
285
286
int n = read1(cbuf, off, len);
287
if (n <= 0) return n;
288
while ((n < len) && in.ready()) {
289
int n1 = read1(cbuf, off + n, len - n);
290
if (n1 <= 0) break;
291
n += n1;
292
}
293
return n;
294
}
295
}
296
297
/**
298
* Reads a line of text. A line is considered to be terminated by any one
299
* of a line feed ('\n'), a carriage return ('\r'), or a carriage return
300
* followed immediately by a linefeed.
301
*
302
* @param ignoreLF If true, the next '\n' will be skipped
303
*
304
* @return A String containing the contents of the line, not including
305
* any line-termination characters, or null if the end of the
306
* stream has been reached
307
*
308
* @see java.io.LineNumberReader#readLine()
309
*
310
* @exception IOException If an I/O error occurs
311
*/
312
String readLine(boolean ignoreLF) throws IOException {
313
StringBuilder s = null;
314
int startChar;
315
316
synchronized (lock) {
317
ensureOpen();
318
boolean omitLF = ignoreLF || skipLF;
319
320
bufferLoop:
321
for (;;) {
322
323
if (nextChar >= nChars)
324
fill();
325
if (nextChar >= nChars) { /* EOF */
326
if (s != null && s.length() > 0)
327
return s.toString();
328
else
329
return null;
330
}
331
boolean eol = false;
332
char c = 0;
333
int i;
334
335
/* Skip a leftover '\n', if necessary */
336
if (omitLF && (cb[nextChar] == '\n'))
337
nextChar++;
338
skipLF = false;
339
omitLF = false;
340
341
charLoop:
342
for (i = nextChar; i < nChars; i++) {
343
c = cb[i];
344
if ((c == '\n') || (c == '\r')) {
345
eol = true;
346
break charLoop;
347
}
348
}
349
350
startChar = nextChar;
351
nextChar = i;
352
353
if (eol) {
354
String str;
355
if (s == null) {
356
str = new String(cb, startChar, i - startChar);
357
} else {
358
s.append(cb, startChar, i - startChar);
359
str = s.toString();
360
}
361
nextChar++;
362
if (c == '\r') {
363
skipLF = true;
364
}
365
return str;
366
}
367
368
if (s == null)
369
s = new StringBuilder(defaultExpectedLineLength);
370
s.append(cb, startChar, i - startChar);
371
}
372
}
373
}
374
375
/**
376
* Reads a line of text. A line is considered to be terminated by any one
377
* of a line feed ('\n'), a carriage return ('\r'), or a carriage return
378
* followed immediately by a linefeed.
379
*
380
* @return A String containing the contents of the line, not including
381
* any line-termination characters, or null if the end of the
382
* stream has been reached
383
*
384
* @exception IOException If an I/O error occurs
385
*
386
* @see java.nio.file.Files#readAllLines
387
*/
388
public String readLine() throws IOException {
389
return readLine(false);
390
}
391
392
/**
393
* Skips characters.
394
*
395
* @param n The number of characters to skip
396
*
397
* @return The number of characters actually skipped
398
*
399
* @exception IllegalArgumentException If <code>n</code> is negative.
400
* @exception IOException If an I/O error occurs
401
*/
402
public long skip(long n) throws IOException {
403
if (n < 0L) {
404
throw new IllegalArgumentException("skip value is negative");
405
}
406
synchronized (lock) {
407
ensureOpen();
408
long r = n;
409
while (r > 0) {
410
if (nextChar >= nChars)
411
fill();
412
if (nextChar >= nChars) /* EOF */
413
break;
414
if (skipLF) {
415
skipLF = false;
416
if (cb[nextChar] == '\n') {
417
nextChar++;
418
}
419
}
420
long d = nChars - nextChar;
421
if (r <= d) {
422
nextChar += r;
423
r = 0;
424
break;
425
}
426
else {
427
r -= d;
428
nextChar = nChars;
429
}
430
}
431
return n - r;
432
}
433
}
434
435
/**
436
* Tells whether this stream is ready to be read. A buffered character
437
* stream is ready if the buffer is not empty, or if the underlying
438
* character stream is ready.
439
*
440
* @exception IOException If an I/O error occurs
441
*/
442
public boolean ready() throws IOException {
443
synchronized (lock) {
444
ensureOpen();
445
446
/*
447
* If newline needs to be skipped and the next char to be read
448
* is a newline character, then just skip it right away.
449
*/
450
if (skipLF) {
451
/* Note that in.ready() will return true if and only if the next
452
* read on the stream will not block.
453
*/
454
if (nextChar >= nChars && in.ready()) {
455
fill();
456
}
457
if (nextChar < nChars) {
458
if (cb[nextChar] == '\n')
459
nextChar++;
460
skipLF = false;
461
}
462
}
463
return (nextChar < nChars) || in.ready();
464
}
465
}
466
467
/**
468
* Tells whether this stream supports the mark() operation, which it does.
469
*/
470
public boolean markSupported() {
471
return true;
472
}
473
474
/**
475
* Marks the present position in the stream. Subsequent calls to reset()
476
* will attempt to reposition the stream to this point.
477
*
478
* @param readAheadLimit Limit on the number of characters that may be
479
* read while still preserving the mark. An attempt
480
* to reset the stream after reading characters
481
* up to this limit or beyond may fail.
482
* A limit value larger than the size of the input
483
* buffer will cause a new buffer to be allocated
484
* whose size is no smaller than limit.
485
* Therefore large values should be used with care.
486
*
487
* @exception IllegalArgumentException If {@code readAheadLimit < 0}
488
* @exception IOException If an I/O error occurs
489
*/
490
public void mark(int readAheadLimit) throws IOException {
491
if (readAheadLimit < 0) {
492
throw new IllegalArgumentException("Read-ahead limit < 0");
493
}
494
synchronized (lock) {
495
ensureOpen();
496
this.readAheadLimit = readAheadLimit;
497
markedChar = nextChar;
498
markedSkipLF = skipLF;
499
}
500
}
501
502
/**
503
* Resets the stream to the most recent mark.
504
*
505
* @exception IOException If the stream has never been marked,
506
* or if the mark has been invalidated
507
*/
508
public void reset() throws IOException {
509
synchronized (lock) {
510
ensureOpen();
511
if (markedChar < 0)
512
throw new IOException((markedChar == INVALIDATED)
513
? "Mark invalid"
514
: "Stream not marked");
515
nextChar = markedChar;
516
skipLF = markedSkipLF;
517
}
518
}
519
520
public void close() throws IOException {
521
synchronized (lock) {
522
if (in == null)
523
return;
524
try {
525
in.close();
526
} finally {
527
in = null;
528
cb = null;
529
}
530
}
531
}
532
533
/**
534
* Returns a {@code Stream}, the elements of which are lines read from
535
* this {@code BufferedReader}. The {@link Stream} is lazily populated,
536
* i.e., read only occurs during the
537
* <a href="../util/stream/package-summary.html#StreamOps">terminal
538
* stream operation</a>.
539
*
540
* <p> The reader must not be operated on during the execution of the
541
* terminal stream operation. Otherwise, the result of the terminal stream
542
* operation is undefined.
543
*
544
* <p> After execution of the terminal stream operation there are no
545
* guarantees that the reader will be at a specific position from which to
546
* read the next character or line.
547
*
548
* <p> If an {@link IOException} is thrown when accessing the underlying
549
* {@code BufferedReader}, it is wrapped in an {@link
550
* UncheckedIOException} which will be thrown from the {@code Stream}
551
* method that caused the read to take place. This method will return a
552
* Stream if invoked on a BufferedReader that is closed. Any operation on
553
* that stream that requires reading from the BufferedReader after it is
554
* closed, will cause an UncheckedIOException to be thrown.
555
*
556
* @return a {@code Stream<String>} providing the lines of text
557
* described by this {@code BufferedReader}
558
*
559
* @since 1.8
560
*/
561
public Stream<String> lines() {
562
Iterator<String> iter = new Iterator<String>() {
563
String nextLine = null;
564
565
@Override
566
public boolean hasNext() {
567
if (nextLine != null) {
568
return true;
569
} else {
570
try {
571
nextLine = readLine();
572
return (nextLine != null);
573
} catch (IOException e) {
574
throw new UncheckedIOException(e);
575
}
576
}
577
}
578
579
@Override
580
public String next() {
581
if (nextLine != null || hasNext()) {
582
String line = nextLine;
583
nextLine = null;
584
return line;
585
} else {
586
throw new NoSuchElementException();
587
}
588
}
589
};
590
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(
591
iter, Spliterator.ORDERED | Spliterator.NONNULL), false);
592
}
593
}
594
595