Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/share/classes/java/nio/channels/Channels.java
41159 views
1
/*
2
* Copyright (c) 2000, 2021, 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.nio.channels;
27
28
import java.io.FileInputStream;
29
import java.io.FileOutputStream;
30
import java.io.InputStream;
31
import java.io.OutputStream;
32
import java.io.Reader;
33
import java.io.Writer;
34
import java.io.IOException;
35
import java.nio.ByteBuffer;
36
import java.nio.charset.Charset;
37
import java.nio.charset.CharsetDecoder;
38
import java.nio.charset.CharsetEncoder;
39
import java.nio.charset.UnsupportedCharsetException;
40
import java.nio.channels.spi.AbstractInterruptibleChannel;
41
import java.util.Objects;
42
import java.util.concurrent.ExecutionException;
43
import sun.nio.ch.ChannelInputStream;
44
import sun.nio.cs.StreamDecoder;
45
import sun.nio.cs.StreamEncoder;
46
47
48
/**
49
* Utility methods for channels and streams.
50
*
51
* <p> This class defines static methods that support the interoperation of the
52
* stream classes of the {@link java.io} package with the channel classes
53
* of this package. </p>
54
*
55
*
56
* @author Mark Reinhold
57
* @author Mike McCloskey
58
* @author JSR-51 Expert Group
59
* @since 1.4
60
*/
61
62
public final class Channels {
63
64
private Channels() { throw new Error("no instances"); }
65
66
/**
67
* Write all remaining bytes in buffer to the given channel.
68
* If the channel is selectable then it must be configured blocking.
69
*/
70
private static void writeFullyImpl(WritableByteChannel ch, ByteBuffer bb)
71
throws IOException
72
{
73
while (bb.remaining() > 0) {
74
int n = ch.write(bb);
75
if (n <= 0)
76
throw new RuntimeException("no bytes written");
77
}
78
}
79
80
/**
81
* Write all remaining bytes in buffer to the given channel.
82
*
83
* @throws IllegalBlockingModeException
84
* If the channel is selectable and configured non-blocking.
85
*/
86
private static void writeFully(WritableByteChannel ch, ByteBuffer bb)
87
throws IOException
88
{
89
if (ch instanceof SelectableChannel sc) {
90
synchronized (sc.blockingLock()) {
91
if (!sc.isBlocking())
92
throw new IllegalBlockingModeException();
93
writeFullyImpl(ch, bb);
94
}
95
} else {
96
writeFullyImpl(ch, bb);
97
}
98
}
99
100
// -- Byte streams from channels --
101
102
/**
103
* Constructs a stream that reads bytes from the given channel.
104
*
105
* <p> The {@code read} methods of the resulting stream will throw an
106
* {@link IllegalBlockingModeException} if invoked while the underlying
107
* channel is in non-blocking mode. The stream will not be buffered, and
108
* it will not support the {@link InputStream#mark mark} or {@link
109
* InputStream#reset reset} methods. The stream will be safe for access by
110
* multiple concurrent threads. Closing the stream will in turn cause the
111
* channel to be closed. </p>
112
*
113
* @param ch
114
* The channel from which bytes will be read
115
*
116
* @return A new input stream
117
*/
118
public static InputStream newInputStream(ReadableByteChannel ch) {
119
Objects.requireNonNull(ch, "ch");
120
return new ChannelInputStream(ch);
121
}
122
123
/**
124
* Constructs a stream that writes bytes to the given channel.
125
*
126
* <p> The {@code write} methods of the resulting stream will throw an
127
* {@link IllegalBlockingModeException} if invoked while the underlying
128
* channel is in non-blocking mode. The stream will not be buffered. The
129
* stream will be safe for access by multiple concurrent threads. Closing
130
* the stream will in turn cause the channel to be closed. </p>
131
*
132
* @param ch
133
* The channel to which bytes will be written
134
*
135
* @return A new output stream
136
*/
137
public static OutputStream newOutputStream(WritableByteChannel ch) {
138
Objects.requireNonNull(ch, "ch");
139
140
return new OutputStream() {
141
142
private ByteBuffer bb;
143
private byte[] bs; // Invoker's previous array
144
private byte[] b1;
145
146
@Override
147
public synchronized void write(int b) throws IOException {
148
if (b1 == null)
149
b1 = new byte[1];
150
b1[0] = (byte) b;
151
this.write(b1);
152
}
153
154
@Override
155
public synchronized void write(byte[] bs, int off, int len)
156
throws IOException
157
{
158
if ((off < 0) || (off > bs.length) || (len < 0) ||
159
((off + len) > bs.length) || ((off + len) < 0)) {
160
throw new IndexOutOfBoundsException();
161
} else if (len == 0) {
162
return;
163
}
164
ByteBuffer bb = ((this.bs == bs)
165
? this.bb
166
: ByteBuffer.wrap(bs));
167
bb.limit(Math.min(off + len, bb.capacity()));
168
bb.position(off);
169
this.bb = bb;
170
this.bs = bs;
171
Channels.writeFully(ch, bb);
172
}
173
174
@Override
175
public void close() throws IOException {
176
ch.close();
177
}
178
179
};
180
}
181
182
/**
183
* Constructs a stream that reads bytes from the given channel.
184
*
185
* <p> The stream will not be buffered, and it will not support the {@link
186
* InputStream#mark mark} or {@link InputStream#reset reset} methods. The
187
* stream will be safe for access by multiple concurrent threads. Closing
188
* the stream will in turn cause the channel to be closed. </p>
189
*
190
* @param ch
191
* The channel from which bytes will be read
192
*
193
* @return A new input stream
194
*
195
* @since 1.7
196
*/
197
public static InputStream newInputStream(AsynchronousByteChannel ch) {
198
Objects.requireNonNull(ch, "ch");
199
return new InputStream() {
200
201
private ByteBuffer bb;
202
private byte[] bs; // Invoker's previous array
203
private byte[] b1;
204
205
@Override
206
public synchronized int read() throws IOException {
207
if (b1 == null)
208
b1 = new byte[1];
209
int n = this.read(b1);
210
if (n == 1)
211
return b1[0] & 0xff;
212
return -1;
213
}
214
215
@Override
216
public synchronized int read(byte[] bs, int off, int len)
217
throws IOException
218
{
219
if ((off < 0) || (off > bs.length) || (len < 0) ||
220
((off + len) > bs.length) || ((off + len) < 0)) {
221
throw new IndexOutOfBoundsException();
222
} else if (len == 0) {
223
return 0;
224
}
225
226
ByteBuffer bb = ((this.bs == bs)
227
? this.bb
228
: ByteBuffer.wrap(bs));
229
bb.position(off);
230
bb.limit(Math.min(off + len, bb.capacity()));
231
this.bb = bb;
232
this.bs = bs;
233
234
boolean interrupted = false;
235
try {
236
for (;;) {
237
try {
238
return ch.read(bb).get();
239
} catch (ExecutionException ee) {
240
throw new IOException(ee.getCause());
241
} catch (InterruptedException ie) {
242
interrupted = true;
243
}
244
}
245
} finally {
246
if (interrupted)
247
Thread.currentThread().interrupt();
248
}
249
}
250
251
@Override
252
public void close() throws IOException {
253
ch.close();
254
}
255
};
256
}
257
258
/**
259
* Constructs a stream that writes bytes to the given channel.
260
*
261
* <p> The stream will not be buffered. The stream will be safe for access
262
* by multiple concurrent threads. Closing the stream will in turn cause
263
* the channel to be closed. </p>
264
*
265
* @param ch
266
* The channel to which bytes will be written
267
*
268
* @return A new output stream
269
*
270
* @since 1.7
271
*/
272
public static OutputStream newOutputStream(AsynchronousByteChannel ch) {
273
Objects.requireNonNull(ch, "ch");
274
return new OutputStream() {
275
276
private ByteBuffer bb;
277
private byte[] bs; // Invoker's previous array
278
private byte[] b1;
279
280
@Override
281
public synchronized void write(int b) throws IOException {
282
if (b1 == null)
283
b1 = new byte[1];
284
b1[0] = (byte) b;
285
this.write(b1);
286
}
287
288
@Override
289
public synchronized void write(byte[] bs, int off, int len)
290
throws IOException
291
{
292
if ((off < 0) || (off > bs.length) || (len < 0) ||
293
((off + len) > bs.length) || ((off + len) < 0)) {
294
throw new IndexOutOfBoundsException();
295
} else if (len == 0) {
296
return;
297
}
298
ByteBuffer bb = ((this.bs == bs)
299
? this.bb
300
: ByteBuffer.wrap(bs));
301
bb.limit(Math.min(off + len, bb.capacity()));
302
bb.position(off);
303
this.bb = bb;
304
this.bs = bs;
305
306
boolean interrupted = false;
307
try {
308
while (bb.remaining() > 0) {
309
try {
310
ch.write(bb).get();
311
} catch (ExecutionException ee) {
312
throw new IOException(ee.getCause());
313
} catch (InterruptedException ie) {
314
interrupted = true;
315
}
316
}
317
} finally {
318
if (interrupted)
319
Thread.currentThread().interrupt();
320
}
321
}
322
323
@Override
324
public void close() throws IOException {
325
ch.close();
326
}
327
};
328
}
329
330
331
// -- Channels from streams --
332
333
/**
334
* Constructs a channel that reads bytes from the given stream.
335
*
336
* <p> The resulting channel will not be buffered; it will simply redirect
337
* its I/O operations to the given stream. Closing the channel will in
338
* turn cause the stream to be closed. </p>
339
*
340
* @param in
341
* The stream from which bytes are to be read
342
*
343
* @return A new readable byte channel
344
*/
345
public static ReadableByteChannel newChannel(InputStream in) {
346
Objects.requireNonNull(in, "in");
347
348
if (in.getClass() == FileInputStream.class) {
349
return ((FileInputStream) in).getChannel();
350
}
351
352
return new ReadableByteChannelImpl(in);
353
}
354
355
private static class ReadableByteChannelImpl
356
extends AbstractInterruptibleChannel // Not really interruptible
357
implements ReadableByteChannel
358
{
359
private final InputStream in;
360
private static final int TRANSFER_SIZE = 8192;
361
private byte[] buf = new byte[0];
362
private final Object readLock = new Object();
363
364
ReadableByteChannelImpl(InputStream in) {
365
this.in = in;
366
}
367
368
@Override
369
public int read(ByteBuffer dst) throws IOException {
370
if (!isOpen()) {
371
throw new ClosedChannelException();
372
}
373
374
int len = dst.remaining();
375
int totalRead = 0;
376
int bytesRead = 0;
377
synchronized (readLock) {
378
while (totalRead < len) {
379
int bytesToRead = Math.min((len - totalRead),
380
TRANSFER_SIZE);
381
if (buf.length < bytesToRead)
382
buf = new byte[bytesToRead];
383
if ((totalRead > 0) && !(in.available() > 0))
384
break; // block at most once
385
try {
386
begin();
387
bytesRead = in.read(buf, 0, bytesToRead);
388
} finally {
389
end(bytesRead > 0);
390
}
391
if (bytesRead < 0)
392
break;
393
else
394
totalRead += bytesRead;
395
dst.put(buf, 0, bytesRead);
396
}
397
if ((bytesRead < 0) && (totalRead == 0))
398
return -1;
399
400
return totalRead;
401
}
402
}
403
404
@Override
405
protected void implCloseChannel() throws IOException {
406
in.close();
407
}
408
}
409
410
411
/**
412
* Constructs a channel that writes bytes to the given stream.
413
*
414
* <p> The resulting channel will not be buffered; it will simply redirect
415
* its I/O operations to the given stream. Closing the channel will in
416
* turn cause the stream to be closed. </p>
417
*
418
* @param out
419
* The stream to which bytes are to be written
420
*
421
* @return A new writable byte channel
422
*/
423
public static WritableByteChannel newChannel(OutputStream out) {
424
Objects.requireNonNull(out, "out");
425
426
if (out.getClass() == FileOutputStream.class) {
427
return ((FileOutputStream) out).getChannel();
428
}
429
430
return new WritableByteChannelImpl(out);
431
}
432
433
private static class WritableByteChannelImpl
434
extends AbstractInterruptibleChannel // Not really interruptible
435
implements WritableByteChannel
436
{
437
private final OutputStream out;
438
private static final int TRANSFER_SIZE = 8192;
439
private byte[] buf = new byte[0];
440
private final Object writeLock = new Object();
441
442
WritableByteChannelImpl(OutputStream out) {
443
this.out = out;
444
}
445
446
@Override
447
public int write(ByteBuffer src) throws IOException {
448
if (!isOpen()) {
449
throw new ClosedChannelException();
450
}
451
452
int len = src.remaining();
453
int totalWritten = 0;
454
synchronized (writeLock) {
455
while (totalWritten < len) {
456
int bytesToWrite = Math.min((len - totalWritten),
457
TRANSFER_SIZE);
458
if (buf.length < bytesToWrite)
459
buf = new byte[bytesToWrite];
460
src.get(buf, 0, bytesToWrite);
461
try {
462
begin();
463
out.write(buf, 0, bytesToWrite);
464
} finally {
465
end(bytesToWrite > 0);
466
}
467
totalWritten += bytesToWrite;
468
}
469
return totalWritten;
470
}
471
}
472
473
@Override
474
protected void implCloseChannel() throws IOException {
475
out.close();
476
}
477
}
478
479
480
// -- Character streams from channels --
481
482
/**
483
* Constructs a reader that decodes bytes from the given channel using the
484
* given decoder.
485
*
486
* <p> The resulting stream will contain an internal input buffer of at
487
* least {@code minBufferCap} bytes. The stream's {@code read} methods
488
* will, as needed, fill the buffer by reading bytes from the underlying
489
* channel; if the channel is in non-blocking mode when bytes are to be
490
* read then an {@link IllegalBlockingModeException} will be thrown. The
491
* resulting stream will not otherwise be buffered, and it will not support
492
* the {@link Reader#mark mark} or {@link Reader#reset reset} methods.
493
* Closing the stream will in turn cause the channel to be closed. </p>
494
*
495
* @param ch
496
* The channel from which bytes will be read
497
*
498
* @param dec
499
* The charset decoder to be used
500
*
501
* @param minBufferCap
502
* The minimum capacity of the internal byte buffer,
503
* or {@code -1} if an implementation-dependent
504
* default capacity is to be used
505
*
506
* @return A new reader
507
*/
508
public static Reader newReader(ReadableByteChannel ch,
509
CharsetDecoder dec,
510
int minBufferCap)
511
{
512
Objects.requireNonNull(ch, "ch");
513
return StreamDecoder.forDecoder(ch, dec.reset(), minBufferCap);
514
}
515
516
/**
517
* Constructs a reader that decodes bytes from the given channel according
518
* to the named charset.
519
*
520
* <p> An invocation of this method of the form
521
*
522
* <pre> {@code
523
* Channels.newReader(ch, csname)
524
* } </pre>
525
*
526
* behaves in exactly the same way as the expression
527
*
528
* <pre> {@code
529
* Channels.newReader(ch, Charset.forName(csName))
530
* } </pre>
531
*
532
* @param ch
533
* The channel from which bytes will be read
534
*
535
* @param csName
536
* The name of the charset to be used
537
*
538
* @return A new reader
539
*
540
* @throws UnsupportedCharsetException
541
* If no support for the named charset is available
542
* in this instance of the Java virtual machine
543
*/
544
public static Reader newReader(ReadableByteChannel ch,
545
String csName)
546
{
547
Objects.requireNonNull(csName, "csName");
548
return newReader(ch, Charset.forName(csName).newDecoder(), -1);
549
}
550
551
/**
552
* Constructs a reader that decodes bytes from the given channel according
553
* to the given charset.
554
*
555
* <p> An invocation of this method of the form
556
*
557
* <pre> {@code
558
* Channels.newReader(ch, charset)
559
* } </pre>
560
*
561
* behaves in exactly the same way as the expression
562
*
563
* <pre> {@code
564
* Channels.newReader(ch, Charset.forName(csName).newDecoder(), -1)
565
* } </pre>
566
*
567
* <p> The reader's default action for malformed-input and unmappable-character
568
* errors is to {@linkplain java.nio.charset.CodingErrorAction#REPORT report}
569
* them. When more control over the error handling is required, the constructor
570
* that takes a {@linkplain java.nio.charset.CharsetDecoder} should be used.
571
*
572
* @param ch The channel from which bytes will be read
573
*
574
* @param charset The charset to be used
575
*
576
* @return A new reader
577
*/
578
public static Reader newReader(ReadableByteChannel ch, Charset charset) {
579
Objects.requireNonNull(charset, "charset");
580
return newReader(ch, charset.newDecoder(), -1);
581
}
582
583
/**
584
* Constructs a writer that encodes characters using the given encoder and
585
* writes the resulting bytes to the given channel.
586
*
587
* <p> The resulting stream will contain an internal output buffer of at
588
* least {@code minBufferCap} bytes. The stream's {@code write} methods
589
* will, as needed, flush the buffer by writing bytes to the underlying
590
* channel; if the channel is in non-blocking mode when bytes are to be
591
* written then an {@link IllegalBlockingModeException} will be thrown.
592
* The resulting stream will not otherwise be buffered. Closing the stream
593
* will in turn cause the channel to be closed. </p>
594
*
595
* @param ch
596
* The channel to which bytes will be written
597
*
598
* @param enc
599
* The charset encoder to be used
600
*
601
* @param minBufferCap
602
* The minimum capacity of the internal byte buffer,
603
* or {@code -1} if an implementation-dependent
604
* default capacity is to be used
605
*
606
* @return A new writer
607
*/
608
public static Writer newWriter(WritableByteChannel ch,
609
CharsetEncoder enc,
610
int minBufferCap)
611
{
612
Objects.requireNonNull(ch, "ch");
613
return StreamEncoder.forEncoder(ch, enc.reset(), minBufferCap);
614
}
615
616
/**
617
* Constructs a writer that encodes characters according to the named
618
* charset and writes the resulting bytes to the given channel.
619
*
620
* <p> An invocation of this method of the form
621
*
622
* <pre> {@code
623
* Channels.newWriter(ch, csname)
624
* } </pre>
625
*
626
* behaves in exactly the same way as the expression
627
*
628
* <pre> {@code
629
* Channels.newWriter(ch, Charset.forName(csName))
630
* } </pre>
631
*
632
* @param ch
633
* The channel to which bytes will be written
634
*
635
* @param csName
636
* The name of the charset to be used
637
*
638
* @return A new writer
639
*
640
* @throws UnsupportedCharsetException
641
* If no support for the named charset is available
642
* in this instance of the Java virtual machine
643
*/
644
public static Writer newWriter(WritableByteChannel ch,
645
String csName)
646
{
647
Objects.requireNonNull(csName, "csName");
648
return newWriter(ch, Charset.forName(csName).newEncoder(), -1);
649
}
650
651
/**
652
* Constructs a writer that encodes characters according to the given
653
* charset and writes the resulting bytes to the given channel.
654
*
655
* <p> An invocation of this method of the form
656
*
657
* <pre> {@code
658
* Channels.newWriter(ch, charset)
659
* } </pre>
660
*
661
* behaves in exactly the same way as the expression
662
*
663
* <pre> {@code
664
* Channels.newWriter(ch, Charset.forName(csName).newEncoder(), -1)
665
* } </pre>
666
*
667
* <p> The writer's default action for malformed-input and unmappable-character
668
* errors is to {@linkplain java.nio.charset.CodingErrorAction#REPORT report}
669
* them. When more control over the error handling is required, the constructor
670
* that takes a {@linkplain java.nio.charset.CharsetEncoder} should be used.
671
*
672
* @param ch
673
* The channel to which bytes will be written
674
*
675
* @param charset
676
* The charset to be used
677
*
678
* @return A new writer
679
*/
680
public static Writer newWriter(WritableByteChannel ch, Charset charset) {
681
Objects.requireNonNull(charset, "charset");
682
return newWriter(ch, charset.newEncoder(), -1);
683
}
684
}
685
686