通道(Channel)与流的区别:
- 通道可以同时进行读写,而流只能读或写
- 通道可以实现异步读写数据
- 通道可以从缓冲读数据,也可以写数据到缓冲
Channel 是NIO的一个接口,常用的Channel类有:FileChannel、DatagramChannel、ServerSocketChannel( 类似 ServerSocket ) 和 SocketChannel (类似 Socket 当客户端连接 Server的时候,会由 ServerSocketChannel 产生一个对应客户端的 SocketChannel)
FileChannel: 主要用来对本地文件进行IO操作
方法名 | 作用 |
public abstract int read(ByteBuffer dst) | 从通道读取数据并放入缓冲区中 |
public abstract int write(ByteBuffer src) | 把缓冲区的数据写到通道中 |
public abstract long transferFrom(ReadableByteChannel src, long position, long count) | 从目标通道中复制数据到当前通道 |
public abstract long transferTo(long position, long count, WritableByteChannel target) | 把数据从当前通道复制给目标通道 |
写文件 示例代码:
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;
public class NIOFileChannel {
public static void main(String[] args) throws IOException {
String str = "Hi, NIO";
// 创建一个输出流->channel
FileOutputStream fileOutputStream = new FileOutputStream("d:\\file.txt");
// 通过fileOutStream 获得对应的FileChannel(FileChannelImpl)
FileChannel fileChannel = fileOutputStream.getChannel();
// 创建一个缓冲区 byteBuffer
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
byteBuffer.put(str.getBytes(StandardCharsets.UTF_8));
// 对buffer进行翻转
byteBuffer.flip();
// 将bytebuffer 数据写入到fileChannel
fileChannel.write(byteBuffer);
fileOutputStream.close();
}
}
读文件 示例代码:
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
/**
* @author doubily
* 文件读取
*/
public class NIOReadFileChannel {
public static void main(String[] args) throws IOException {
// 创建文件的输入流
File file = new File("d:\\file.txt");
FileInputStream fileInputStream = new FileInputStream(file);
// 通过FileInputStream 获取对应的FileChannel -> 实际类型 FileChannelImpl
FileChannel fileChannel = fileInputStream.getChannel();
// 创建缓冲区
ByteBuffer byteBuffer = ByteBuffer.allocate((int)file.length());
// 将 通道数据读入到Buffer
fileChannel.read(byteBuffer);
// 将byteBuffer 的字节数据 转成String
System.out.println(new String(byteBuffer.array()));
fileInputStream.close();
}
}
复制文件 示例代码:
/**
* @author doubily
* 文件拷贝
*/
public class NIODuplicateFileChannel {
public static void main(String[] args) throws IOException {
FileInputStream fileInputStream = new FileInputStream("D:/file.txt");
FileChannel fileChannelRead = fileInputStream.getChannel();
FileOutputStream fileOutputStream = new FileOutputStream("D:/file01.txt");
FileChannel fileChannelWrite = fileOutputStream.getChannel();
// ByteBuffer byteBuffer = ByteBuffer.allocate(512);
// while (true) {
// // 复位 清空buf 避免position和limit相等,循环返回0
// byteBuffer.clear();
// int read = fileChannelRead.read(byteBuffer);
// // 读完
// if (read == -1) {
// break;
// }
// // 将buffer 中的数据写入到fileChannelWrite
// byteBuffer.flip();
// fileChannelWrite.write(byteBuffer);
// }
// 使用transferForm 完成拷贝
fileChannelWrite.transferFrom(fileChannelRead, 0, fileChannelRead.size());
// 关闭相关的流
fileChannelRead.close();
fileChannelWrite.close();
fileChannelRead.close();
fileChannelWrite.close();
}
}
ServerSocketChannel : 在服务器端监听新的客户端 Socket 连接
方法 | 说明 |
public static ServerSocketChannel open() | 得到一个 ServerSocketChannel通道 |
public final ServerSocketChannel bind(SocketAddress local) | 设置服务器端端口号 |
public final SelectableChannel configureBlocking(boolean block) | 设置阻塞或非阻塞模式,取值 false表示采用非阻塞模式 |
public SocketChannel accept() | 接受一个连接,返回代表这个连接的通道对家 |
public finalSelectionKeyregister(Selectorsel, int ops) | 注册一个选择器并设置监听事件 |
SocketChannel: 网络 IO 通道, 具体负责进行读写操作。 NIO把缓冲区的数据写入通道,或者把通道里的数据读到缓冲区
方法 | 说明 |
public static SocketChannel open() | 得到一个 SocketChannel通道 |
publicfinalSelectableChannel configureBlocking(boolean block) | 设置阻塞或非阻塞模式,取值false表示采用非阻塞模式 |
public boolean connect(SocketAddress remote) | 连接服务器 |
public boolean finishConnect() | 如果上面的方法连接失败,接下来就要通过该方法完成连接操作 |
public int write(ByteBuffer src) | 往通道里写数据 |
public int read(ByteBuffer dst) | 从通道里读数据 |
public final SelectionKey register(Selector sel, int ops, Object att) | 注册一个选择器并设置监听事件,最后一个参数可以设置共享数据 |
publicfinal void close() | 关闭通道 |