在Java NIO中,通道是用于在实体和字节缓冲区之间有效传输数据的介质。它从一个实体读取数据,并将其放在缓冲区块中以供消费。
通道作为Java NIO提供的网关来访问I/O机制。 通常,通道与操作系统文件描述符具有一对一关系,用于提供平台独立操作功能。
让我们来看看java.nio.channels
类的层次结构:
上述通道可以用于阻塞或非阻塞模式,但是我们主要关注在非阻塞模式下使用通道。
NIO通道基础
通道实现是使用本地代码执行实际工作。通道接口允许我们以便携和受控的方式访问低级I/O服务。
在层次结构的顶部,通道接口如下所示:
package java.nio.channels;
public interface Channel{
public boolean isclose();
public void Open() throws IOException;
}
Java
正如在上述通道接口中看到的,所有通道只有两个常用操作:
- 检查通道是否关闭(
isclose()
) - 打开关闭通道(
close()
)
通道实现
在Java NIO中,主要使用的通道如下:
- FileChannel:文件通道用于从文件读取数据。它只能通过调用
getChannel()
方法来创建对象。不能直接创建FileChannel
对象。
下面是一个创建FileChannel
对象的例子:FileInputStream fis = new FileInputStream("D:\\file-read.txt"); // Path of Input text file ReadableByteChannel rbc = fis.getChannel();
Java
- DatagramChannel:数据报通道可以通过UDP(用户数据报协议)通过网络读取和写入数据。它使用工厂方法来创建新对象。
下面是打开DatagramChannel
的语法:DatagramChannel ch = DatagramChannel.open();
Java
用于关闭DatagramChannel
的语法:DatagramChannel ch = DatagramChannel.close();
Java
- SocketChannel:数据报通道可以通过TCP(传输控制协议)通过网络读取和写入数据。 它还使用工厂方法来创建新对象。
用于打开SocketChannel
的语法:SocketChannel ch = SocketChannel.open(); ch.connect(new InetSocketAddress("somehost", someport));
Java
用于关闭SocketChannel
的语法:SocketChannel ch = SocketChannel.close(); ch.connect(new InetSocketAddress("somehost", someport));
Java
- ServerSocketChannel:
ServerSocketChannel
允许用户监听传入的TCP连接,与Web服务器相同。对于每个传入连接,都会为连接创建一个SocketChannel
。
下面是打开ServerSocketChannel
的语法:ServerSocketChannel ch = ServerSocketChannel.open(); ch.socket().bind (new InetSocketAddress (somelocalport));
Java
下面是关闭ServerSocketChannel
的语法:ServerSocketChannel ch = ServerSocketChannel.close(); ch.socket().bind (new InetSocketAddress (somelocalport));
Java
基本通道示例
下面来看看如何将数据从一个通道复制到另一个通道或从一个文件复制到另一个文件的示例:
package com.yiibai;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
public class ChannelDemo {
public static void main(String args[]) throws IOException {
String relativelyPath = System.getProperty("user.dir");
FileInputStream input = new FileInputStream(relativelyPath + "/testin.txt");
ReadableByteChannel source = input.getChannel();
FileOutputStream output = new FileOutputStream(relativelyPath + "/testout.txt");
WritableByteChannel destination = output.getChannel();
copyData(source, destination);
source.close();
destination.close();
System.out.println("Copy Data finished.");
}
private static void copyData(ReadableByteChannel src, WritableByteChannel dest) throws IOException {
ByteBuffer buffer = ByteBuffer.allocateDirect(20 * 1024);
while (src.read(buffer) != -1) {
// The buffer is used to drained
buffer.flip();
// keep sure that buffer was fully drained
while (buffer.hasRemaining()) {
dest.write(buffer);
}
buffer.clear(); // Now the buffer is empty, ready for the filling
}
}
}
Java
执行上面示例代码,得到以下结果:
Copy Data finished.
Shell
上述程序将文本文件filein.txt
的内容复制到另一个文本文件fileout.txt
。