• 通道(channel):由 java.nio.channels 包定义的。Channel 表示 IO 源与目标打开的连接。Channel 类似于传统的流,只不过 Channel 本身不能直接访问数据,Channel 只能与 Buffer 进行交互。
  • 通道用于源节点与目标节点的连接。在 Java NIO 中负责缓冲区中数据的传输。Channel 本身不存储数据,因此需要配合缓冲区进行传输。

java.nio.channels.Channel 包下:

FileChannel 文件通道
SocketChannel 套接字 通道
ServerSocketChannel 套接字通道服务端
DatagramChannel

获取通道

1、Java 针对支持通道的类提供了 getChannel() 方法
本地 IO:
FileInputStream/FileOutputStream .getChannel()
RandomAccessFile

网络 IO:
Socket
ServerSocket
DatagramSocket

以上几个类都可以通过调用 getChannel() 方法获取通道

2、在 JDK1.7 中的 NIO.2 针对各个通道提供了静态方法 open()

3、在 JDK1.7 中的 NIO.2 的 Files 工具类的 newByteChannel() 方法

 package io.h_nio.channel;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.SeekableByteChannel;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;

/**
 * nio的channel
 * 准备  D盘下创建: wangzijian.txt
 *
 * @author zijian Wang
 */
public class NioChannel {

    public static void main(String[] args) {
//        read_01();
//        read_02();
//        read_03();
//        writer();
        transfer();
    }

    /**
     * 使用BufferedInputStream缓冲字节流去读
     */
    private static void read_01() {
        try (
                BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("D:\\wangzijian.txt"));
                ReadableByteChannel readableByteChannel = Channels.newChannel(bufferedInputStream);
        ) {
            ByteBuffer dst = ByteBuffer.allocate(10);
            readableByteChannel.read(dst);
            System.out.println(new String(dst.array()));

        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 使用文件字节流获取FileChannel
     */
    private static void read_02() {
        try (
                FileInputStream fileInputStream = new FileInputStream("D://wangzijian.txt");
                FileChannel fileChannel = fileInputStream.getChannel();
        ) {
            ByteBuffer dst = ByteBuffer.allocate(10);
            fileChannel.read(dst);
            System.out.println(new String(dst.array()));

        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 使用文件字节流获取FileChannel
     */
    private static void read_03() {
        try (
                SeekableByteChannel fileChannel = Files.newByteChannel(Paths.get("D://wangzijian.txt"));
        ) {
            ByteBuffer byteBuffer = ByteBuffer.allocate(10);
            while (fileChannel.read(byteBuffer) > 0) {
                byteBuffer.flip();
                System.out.print(Charset.forName("UTF-8").decode(byteBuffer));
                byteBuffer.clear();
            }
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 使用文件字节流获取FileChannel
     * 读取文件中的数据,使用多个buffer写入到另一个文件中。
     */
    private static void writer() {
        try (
                FileInputStream fileInputStream = new FileInputStream("D://wangzijian.txt");
                FileChannel inputStreamChannel = fileInputStream.getChannel();
                FileOutputStream fileOutputStream = new FileOutputStream("D://wangzijian_w1.txt");
                FileChannel outputStreamChannel = fileOutputStream.getChannel();
        ) {
            ByteBuffer dst1 = ByteBuffer.allocate(5);
            ByteBuffer dst2 = ByteBuffer.allocate(5);
            ByteBuffer[] byteBuffers = new ByteBuffer[]{dst1, dst2};

            inputStreamChannel.read(byteBuffers);
            dst1.flip();
            dst2.flip();
            System.out.println(new String(dst1.array()));
            System.out.println(new String(dst2.array()));

            outputStreamChannel.write(byteBuffers);

        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     *
     */
    private static void transfer() {

        try (
                FileInputStream fileInputStream = new FileInputStream("D://wangzijian.txt");
                FileChannel inputStreamChannel = fileInputStream.getChannel();

                FileOutputStream fileOutputStream = new FileOutputStream("D://wangzijian_w1.txt");
                FileChannel outputStreamChannel = fileOutputStream.getChannel();
        ) {
            ByteBuffer buffer = ByteBuffer.allocate(20);

            inputStreamChannel.read(buffer);

            //将字节从给定的可读字节通道传输到此通道的文件中
            outputStreamChannel.transferFrom(inputStreamChannel, 0, buffer.capacity());
            //将字节从此通道的文件传输到给定的可写字节通道。
            inputStreamChannel.transferTo(0, buffer.capacity(), outputStreamChannel);

            buffer.flip();
            System.out.println(new String(buffer.array()));
            outputStreamChannel.write(buffer);

        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

}