All Downloads are FREE. Search and download functionalities are using the official Maven repository.

java.nio.channels.Channels Maven / Gradle / Ivy

/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package java.nio.channels;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.nio.ByteBuffer;
import java.nio.channels.spi.AbstractInterruptibleChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import libcore.io.Streams;

/**
 * This class provides several utilities to get I/O streams from channels.
 */
public final class Channels {

    private Channels() {}

    /**
     * Returns an input stream on the given channel. The resulting stream has
     * the following properties:
     * 
    *
  • If the stream is closed, then the underlying channel is closed as * well.
  • *
  • It is thread safe.
  • *
  • It throws an {@link IllegalBlockingModeException} if the channel is * in non-blocking mode and {@code read} is called.
  • *
  • Neither {@code mark} nor {@code reset} is supported.
  • *
  • It is not buffered.
  • *
* * @param channel * the channel to be wrapped by an InputStream. * @return an InputStream that takes bytes from the given byte channel. */ public static InputStream newInputStream(ReadableByteChannel channel) { return new ChannelInputStream(channel); } /** * Returns an output stream on the given channel. The resulting stream has * the following properties: *
    *
  • If the stream is closed, then the underlying channel is closed as * well.
  • *
  • It is thread safe.
  • *
  • It throws an {@link IllegalBlockingModeException} if the channel is * in non-blocking mode and {@code write} is called.
  • *
  • It is not buffered.
  • *
* * @param channel * the channel to be wrapped by an OutputStream. * @return an OutputStream that puts bytes onto the given byte channel. */ public static OutputStream newOutputStream(WritableByteChannel channel) { return new ChannelOutputStream(channel); } /** * Returns a readable channel on the given input stream. The resulting * channel has the following properties: *
    *
  • If the channel is closed, then the underlying stream is closed as * well.
  • *
  • It is not buffered.
  • *
* * @param inputStream * the stream to be wrapped by a byte channel. * @return a byte channel that reads bytes from the input stream. */ public static ReadableByteChannel newChannel(InputStream inputStream) { return new InputStreamChannel(inputStream); } /** * Returns a writable channel on the given output stream. * * The resulting channel has following properties: *
    *
  • If the channel is closed, then the underlying stream is closed as * well.
  • *
  • It is not buffered.
  • *
* * @param outputStream * the stream to be wrapped by a byte channel. * @return a byte channel that writes bytes to the output stream. */ public static WritableByteChannel newChannel(OutputStream outputStream) { return new OutputStreamChannel(outputStream); } /** * Returns a reader that decodes bytes from a channel. * * @param channel * the Channel to be read. * @param decoder * the Charset decoder to be used. * @param minBufferCapacity * The minimum size of the byte buffer, -1 means to use the * default size. * @return the reader. */ public static Reader newReader(ReadableByteChannel channel, CharsetDecoder decoder, int minBufferCapacity) { /* * This method doesn't honor minBufferCapacity. Ignoring that parameter * saves us from having to add a hidden constructor to InputStreamReader. */ return new InputStreamReader(new ChannelInputStream(channel), decoder); } /** * Returns a reader that decodes bytes from a channel. This method creates a * reader with a buffer of default size. * * @param channel * the Channel to be read. * @param charsetName * the name of the charset. * @return the reader. * @throws java.nio.charset.UnsupportedCharsetException * if the given charset name is not supported. */ public static Reader newReader(ReadableByteChannel channel, String charsetName) { if (charsetName == null) { throw new NullPointerException("charsetName == null"); } return newReader(channel, Charset.forName(charsetName).newDecoder(), -1); } /** * Returns a writer that encodes characters with the specified * {@code encoder} and sends the bytes to the specified channel. * * @param channel * the Channel to write to. * @param encoder * the CharsetEncoder to be used. * @param minBufferCapacity * the minimum size of the byte buffer, -1 means to use the * default size. * @return the writer. */ public static Writer newWriter(WritableByteChannel channel, CharsetEncoder encoder, int minBufferCapacity) { /* * This method doesn't honor minBufferCapacity. Ignoring that parameter * saves us from having to add a hidden constructor to OutputStreamWriter. */ return new OutputStreamWriter(new ChannelOutputStream(channel), encoder); } /** * Returns a writer that encodes characters with the specified * {@code encoder} and sends the bytes to the specified channel. This method * creates a writer with a buffer of default size. * * @param channel * the Channel to be written to. * @param charsetName * the name of the charset. * @return the writer. * @throws java.nio.charset.UnsupportedCharsetException * if the given charset name is not supported. */ public static Writer newWriter(WritableByteChannel channel, String charsetName) { if (charsetName == null) { throw new NullPointerException("charsetName == null"); } return newWriter(channel, Charset.forName(charsetName).newEncoder(), -1); } /** * An input stream that delegates to a readable channel. */ private static class ChannelInputStream extends InputStream { private final ReadableByteChannel channel; ChannelInputStream(ReadableByteChannel channel) { if (channel == null) { throw new NullPointerException("channel == null"); } this.channel = channel; } @Override public synchronized int read() throws IOException { return Streams.readSingleByte(this); } @Override public synchronized int read(byte[] target, int byteOffset, int byteCount) throws IOException { ByteBuffer buffer = ByteBuffer.wrap(target, byteOffset, byteCount); checkBlocking(channel); return channel.read(buffer); } @Override public int available() throws IOException { if (channel instanceof FileChannel) { FileChannel fileChannel = (FileChannel) channel; long result = fileChannel.size() - fileChannel.position(); return result > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) result; } else { return super.available(); } } @Override public synchronized void close() throws IOException { channel.close(); } } /** * An output stream that delegates to a writable channel. */ private static class ChannelOutputStream extends OutputStream { private final WritableByteChannel channel; ChannelOutputStream(WritableByteChannel channel) { if (channel == null) { throw new NullPointerException("channel == null"); } this.channel = channel; } @Override public synchronized void write(int oneByte) throws IOException { byte[] wrappedByte = { (byte) oneByte }; write(wrappedByte); } @Override public synchronized void write(byte[] source, int offset, int length) throws IOException { ByteBuffer buffer = ByteBuffer.wrap(source, offset, length); checkBlocking(channel); int total = 0; while (total < length) { total += channel.write(buffer); } } @Override public synchronized void close() throws IOException { channel.close(); } } static void checkBlocking(Channel channel) { if (channel instanceof SelectableChannel && !((SelectableChannel) channel).isBlocking()) { throw new IllegalBlockingModeException(); } } /** * A readable channel that delegates to an input stream. */ private static class InputStreamChannel extends AbstractInterruptibleChannel implements ReadableByteChannel { private final InputStream inputStream; InputStreamChannel(InputStream inputStream) { if (inputStream == null) { throw new NullPointerException("inputStream == null"); } this.inputStream = inputStream; } public synchronized int read(ByteBuffer target) throws IOException { if (!isOpen()) { throw new ClosedChannelException(); } int bytesRemain = target.remaining(); byte[] bytes = new byte[bytesRemain]; int readCount = 0; try { begin(); readCount = inputStream.read(bytes); } finally { end(readCount >= 0); } if (readCount > 0) { target.put(bytes, 0, readCount); } return readCount; } @Override protected void implCloseChannel() throws IOException { inputStream.close(); } } /** * A writable channel that delegates to an output stream. */ private static class OutputStreamChannel extends AbstractInterruptibleChannel implements WritableByteChannel { private final OutputStream outputStream; OutputStreamChannel(OutputStream outputStream) { if (outputStream == null) { throw new NullPointerException("outputStream == null"); } this.outputStream = outputStream; } public synchronized int write(ByteBuffer source) throws IOException { if (!isOpen()) { throw new ClosedChannelException(); } int bytesRemain = source.remaining(); if (bytesRemain == 0) { return 0; } byte[] buf = new byte[bytesRemain]; source.get(buf); try { begin(); outputStream.write(buf, 0, bytesRemain); } finally { end(bytesRemain >= 0); } return bytesRemain; } @Override protected void implCloseChannel() throws IOException { outputStream.close(); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy