没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
Java NIO
通道
Java NIO 主要需要理解缓冲区、通道、选择器三个核心概念,作为对 Java I/O 的补充, 以提
升大批量数据传输的效率。
通道(Channel)作为 NIO 的三大核心概念之一(缓冲区、通道、选择器),用于在字节缓冲区与
位于通道另一侧的实体(文件或者套接字)之间有效的传输数据(核心是传输数据)
NIO 编程的一般模式是:把数据填充到发送字节缓冲区 --> 通过通道发送到通道对端文件或
者套接字
通道基础
使用 Channel 的目的是进行数据传输,使用前需要打开通道、使用后需要关闭通道
打开通道
我们知道 I/O 有两大类:File IO 和 Stream I/O,其对应到通道也就有文件通道(FileChannel)
和套接字通道(SocketChannel、ServerSocketChannel、DatagramChannel)两种
对于套接字通道,使用静态工厂方法打开
SocketChannel sc = SocketChannel.open();
ServerSocketChannel sc = ServerSocketChannel.open();
DatagramChannel sc = DatagramChannel.open();
对于文件通道只能通过对一个 RandomAccessFile、FileInputStream、FileOutputStream 对象调
用 getChannel()方法获取
FileInputStream in = new FileInputStream("/tmp/a.txt");
FileChannel fc = in.getChannel();
使用通道进行数据传输
下段代码首先将要写入的数据放到 ByteBuffer 中, 然后打开文件通道,把缓冲区中的数据
放到文件通道。
//准备数据并放入字节缓冲区
ByteBuffer bf = ByteBuffer.allocate(1024);
bf.put("i am cool".getBytes());
bf.flip();
//打开文件通道
FileOutputStream out = new FileOutputStream("/tmp/a.txt");
FileChannel fc = out.getChannel();
//数据传输
fc.write(bf);
//关闭通道
fc.close();
关闭通道
如同 Socket、FileInputStream 等对象使用完毕之后需要关闭一样, 通道使用之后也需要关
闭。一个打开的通道代表与一个特定 I/O 服务的特定连接并封装该连接的状态,通道关闭时
连接丢失,不再连接任何东西。
阻塞 & 非阻塞模式
通道有阻塞和非阻塞两种运行模式,非阻塞模式的通道永远不会休眠,请求的操作要么立即
完成,要么返回一个结果表明未进行任何操作(具体看 Socket 通道处的描述)。只有面向
流的通道可使用非阻塞模式
文件通道
文 件 通 道 用 于 对 文 件 进 行 访 问 , 通 过 对 一 个 RandomAccessFile 、 FileInputStream 、
FileOutputStream 对象调用 getChannel()方法获取。调用 getChannel 方法返回一个连接到相
同文件的 FileChannel 对象,该 FileChannel 对象具有与 file 对象相同的访问权限。
文件访问
使用文件通道的目的还是对文件进行读写操作,通道的读写 api 如下:
public abstract int read(ByteBuffer dst) throws IOException;
public abstract int write(ByteBuffer src) throws IOException;
下面是一段读取文件的 Demo
//打开文件 channel
RandomAccessFile f = new RandomAccessFile("/tmp/a.txt", "r");
FileChannel fc = f.getChannel();
//从 channel 中读取数据,直到文件尾
ByteBuffer bb = ByteBuffer.allocate(1024);
while (fc.read(bb) != -1) {
;
}
//翻转(读之前需要先进行翻转)
bb.flip();
StringBuilder builder = new StringBuilder();
//把每一个字节转为字符(ascii 编码)
while (bb.hasRemaining()) {
builder.append((char) bb.get());
}
System.out.println(builder.toString());
上面这个 demo 有个问题:我们只能读取字节, 然后由应用程序去解码,这个问题我们可
以通过工具类 Channels 将通道包装成 Reader 和 Writer 来解决;当然我们也可以直接使用 Java
I/O 流模式的 Reader 和 Writer 操作字符
文件通道位置与文件空洞
文件通道位置(position)就是普通文件的位置, position 的值决定了文件中哪个位置的数据接
下来将被读或者写
读取超出文件尾部位置的数据会返回-1(文件 EOF)
往一个超出文件尾部的位置写入数据会造成文件空洞:比如一个文件现在有 10 个字节, 但
是此时往 position=20 处写入数据就会造成 10~20 之间的位置是没有数据的,这就是文件
空洞
force 操作
force 操作强制通道将全部修改立即应用到磁盘文件(防止系统宕机导致修改丢失)
public abstract void force(boolean metaData) throws IOException;
内存文件映射
FileChannel 提 供 了 一 个 map() 方 法 , 该 方 法 可 以 在 一 个 打 开 的 文 件 和 特 殊 类 型 的
ByteBuffer(MappedByteBuffer)之间建立一个虚拟内存映射。
因为 map 方法返回的 MappedByteBuffer 对象是直接缓冲区,所以通过 MappedByteBuffer 来
操作文件非常高效(尤其是大量数据传输的情况)
MappedByteBuffer 的使用
通过 MappedByteBuffer 读取文件
FileInputStream in = new FileInputStream("/tmp/a.txt");
FileChannel fc = in.getChannel();
MappedByteBuffer mbb = fc.map(MapMode.READ_ONLY, 0, fc.size());
StringBuilder builder = new StringBuilder();
while (mbb.hasRemaining()) {
builder.append((char) mbb.get());
}
System.out.println(builder.toString());
MappedByteBuffer 的三种模式
READ_ONLY
READ_WRITE
PRIVATE
只读和读写模式都好理解,PRIVATE 模式下写操作写的是一个临时缓冲区,不会真正去写文
件。(写时拷贝思想)
Socket 通道
Socket 通道可以运行在非阻塞模式且是可选择的,这两点使得对于网络编程我们不再需要
为每个 Socket 连接创建一个线程,而是使用一个线程即可管理成百上千的 Socket 连接。
所有的 Socket 通道在实例化的时候都会创建一个对象的 Socket 对象, Socket 通道并不负责
协议相关的操作, 协议相关的操作都委派给对等 socket 对象(如 SocketChannel 对象委派
给 Socket 对象)
非阻塞模式
相较于传统 Java Socket 的阻塞模式,SocketChannel 提供了非阻塞模式,以构建高性能的网
络应用程序
剩余12页未读,继续阅读
资源评论
Andy&lin
- 粉丝: 97
- 资源: 214
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 基于STM32使用HAL库实现USB组合设备之多路CDC源码+说明文档.zip
- 金融贸易项目springboot
- mybatis动态sqlSQL 映射 XML 文件是所有 sql 语句
- 基于基于STM32的智能家居系统源码+qt上位机源码.zip
- 深圳房地产资源数据报告
- 基于stm32的智能门禁系统源码+设计文档+演示视频.zip
- cef + chromium 完整源码支持h265和h264
- 基于SpringBoot的API管理平台源代码+数据库,以项目的形式管理API文档,可以进行API的编辑、测试、Mock等操作
- protobuf 3.11版本,静态编译
- 2023NOC创客智慧编程赛项真题图形化-选拔赛(有解析)
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功