I . 通道 ( Channel ) 概念简介
NIO 模型中的 通道 ( Channel ) 组件 :
① NIO 双向读写 : NIO 中的通道 ( Channel ) 是可以双向读写的 , 而 BIO 中的 单一流 ( 输入流 / 输出流 ) 只能读或者只能写 ;
② NIO 异步读写 : NIO 中的通道 ( Channel ) 读写时是异步的 , 全程没有阻塞 ;
③ BIO 同步读写 : BIO 中的流 , 读写时都需要阻塞等待对方回应 ;
④ 通道 ( Channel ) 与 缓冲区 ( Buffer ) : 服务器中 , 通道 ( Channel ) 与 缓冲区 ( Buffer ) 一一对应 , 通道可以读取缓冲区中的数据 , 也可以写出数据到缓冲区中 , 这也是双向读写 ;
II . 通道 ( Channel ) 常用类
通道 ( Channel ) 常用类 : Channel 在 Java 语言 NIO 中被定义成接口 , 常用的实现类有如下 :
① FileChannel : 文件通道 , 用于文件的读写 ;
② ServerSocketChannel : 服务器套接字通道 , 其作用与 BIO 中的 ServerSocket 类似 . 用于 TCP 网络通信中读写数据 ;
③ SocketChannel : 套接字通道 , 其作用与 BIO 中的 Socket 类似 , 用于 TCP 网络通信中读写数据 ;
④ DatagramChannel : 数据包通道 , 用于 UDP 网络通信中读写数据 ;
III . 常用的 通道 ( Channel ) 之 套接字通道 ( SocketChannel )
常用的 通道 ( Channel ) 之 网络套接字通道 ( SocketChannel ) :
① ServerSocketChannel : 在服务器端 , 维护一个 ServerSocketChannel 通道 , 客户端请求服务器通信时 , 服务器端线程会给每个客户端创建一个为该客户端服务的 SocketChannel , 之后服务器与客户端 , 都通过该 SocketChannel 进行通信 ;
② ServerSocketChannel 和 SocketChannel 都是抽象类 :
ServerSocketChannel 是抽象类 , 其真实实现的类型为 ServerSocketChannelImpl ;
SocketChannel 是抽象类 , 其真实类型为 SocketChannelImpl ;
IV . 常用的 通道 ( Channel ) 之 文件通道 ( FileChannel )
常用的 通道 ( Channel ) 之 文件通道 ( FileChannel ) : 主要作用是 读取 , 写入 , 映射 , 操作本地文件 ;
FileChannel 常用方法 : 前两个是 FileChannel 通道与 缓冲区 读写数据 , 后两个是 FileChannel 与其它 通道 读写数据 ;
int read(ByteBuffer dst) : 从 FileChannel 通道中读取数据 , 放入 dst 字节缓冲区中 ;
int write(ByteBuffer src) : 将 src 缓冲区中的数据 , 写入到 FileChannel 通道中 ;
long transferFrom(ReadableByteChannel src, long position, long count) : 将字节数据从 src 通道传输到本 FileChannel 通道中 ;
long transferTo(long position, long count, WritableByteChannel target) : 将字节数据从本 FileChannel 通道传输到 target 通道中 ;
V . 文件通道 ( FileChannel ) 写出文件 示例代码
1 . 示例需求 : 将 “Hello World” 字符串通过 文件通道 ( FileChannel ) 写出到文件中 ;
① 文件通道 ( FileChannel ) 获取 : NIO 中 , 文件通道 ( FileChannel ) 可以从 文件输出流 ( FileOutputStream ) 中进行获取 , 其本质是通过文件输出流 , 向文件中写出数据 ;
② 整体流程 : 先将 “Hello World” 字符串写入 字节缓冲区 ( ByteBuffer ) , 在将字节缓冲区 ( ByteBuffer ) 中的数据 写出到 文件通道 ( FileChannel ) 中 , 最后通过 文件通道 ( FileChannel ) 将数据写出到文件中 ;
2 . 代码示例 :
package kim.hsl.nio; import java.io.FileOutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; public class FileChannelDemo { public static void main(String[] args) { FileOutputStream fos = null; try { String hello = "Hello World"; //1 . FileChannel 可以从 FileOutputStream 中获取 fos = new FileOutputStream("file.txt"); //2 . 创建 FileChannel , 从 FileOutputStream 中可以获取到 //FileChannel 是抽象类 , 实际类型是 FileChannelImpl FileChannel fc = fos.getChannel(); //3 . FileChannel 需要通过 缓冲区 Buffer 才能与数据进行读写交互 ByteBuffer buffer = ByteBuffer.allocate(32); //将数据放入缓冲区中 , flip 方法作用是将 position 位置设置 0 buffer.put(hello.getBytes()); buffer.flip(); //4 . 将 字节缓冲区 ByteBuffer 中的数据写入到 文件通道 FileChannel 中 fc.write(buffer); } catch (IOException e) { e.printStackTrace(); } finally { try { if(fos != null) fos.close(); } catch (IOException e) { e.printStackTrace(); } } } }
执行结果 : 在代码的 src 目录生成 file.txt 文件 , 内容为 Hello World ;