在Java NIO中,Channel被用来I/O传输。Channel就像一个用来在Buffer和另外一头的实体(比如文件)之间传输数据的管道。一个Channel从一个实体里读取数据,并且把数据放到缓冲区(Buffer)里供别人(一般是我们的程序)消费,类似的,我们应该把数据写入到缓冲区里,然后Channel会把缓冲区里的数据传输到I/O的另一端。

Channel是Java NIO提供的用来访问原生的I/O机制的一种途径,我们在编程时应该使用Buffer来和Channel交互,所以,Channel更像是I/O两端实体的桥梁。所谓的Buffer,是Channel用来发送和接收数据的端点。

java-channel-buffer

Channel的特点:

  • 与传统的流(stream)相比,Channel是双向的,既可以写,也可以读。
  • Channel可以把数据读进Buffer,也可以从Buffer里写数据。
  • Channel可以执行异步(asynchronous)的读写操作。
  • Channel可以支持阻塞(blocking)或者非阻塞(non-blocking)模式。
  • 非阻塞的Channel不会使调用的线程进入sleep模式。
  • 基于流的Channel(比如Socket)只能处于非阻塞模式。
  • 数据可以在Channel和Channel之间传输,前提是其中一个Channel是FileChannel。

Java NIO中的Channel类

以下是Java NIO包中提供的两种主要的Channel类实现:

  • FileChannel
    • 文件读写的Channel,不支持非阻塞模式。
  • SocketChannel
    • 有三种Socket Channel类,包括SocketChannel, ServerSocketChannel and DatagramChannel。
    • 可选择(selectable)的Channel,支持非阻塞模式。

一个Java NIO Channel的例子

下面这个例子从文本文件中读数据并且把内容打印到控制台中。我们使用RandomAccessFile和FileChannel把数据读取到ByteBuffer。我们读取512字节的数据到buffer,然后调用buffer的flip方法,使其准备好get操作。一旦我们把数据打印到控制台,我们调用buffer的clear方法,使其可以进行下一次读。如此,一直到文件的末尾。

package com.javapapers.java.nio;

import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class ChannelExample {
    public static void main(String args[]) throws IOException {
        RandomAccessFile file = new RandomAccessFile("temp.txt", "r");
        FileChannel fileChannel = file.getChannel();
        ByteBuffer byteBuffer = ByteBuffer.allocate(512);
        while (fileChannel.read(byteBuffer) > 0) {
            // flip the buffer to prepare for get operation
            byteBuffer.flip();
            while (byteBuffer.hasRemaining()) {
                System.out.print((char) byteBuffer.get());
            }
            // clear the buffer ready for next sequence of read
            byteBuffer.clear();
        }
        file.close();
    }
}

下一篇,我们会详细看下Java NIO的Buffer和各种Channel类。

本文翻译自 http://javapapers.com/java/java-nio-channel/,仅供参考和学习。