Java NIO 详解

nio 的基本组成

1. Buffer

高效的数据容器,除布尔类型,所有原始数据类型都有Buffer实现。

使用步骤:

  1. 写入数据到 Buffer
  2. 调用flip()方法调整指针位置准备读取
  3. 从 Buffer 中读取数据
  4. 调用clear()方法或者compact()方法清理缓存

主要属性值:

  • capacity:Buffer缓冲区大小,只能写入capacity个原始类型。不会改变。
  • position:下一个要被读写的数据的索引。
  • limit:第一个不被读写的数据的索引位置,通常就是缓冲区中实际数据的字节数。

主要方法:

  • flip():反转缓冲区,将limit的值设为position的值, 然后position的值设为0。为从缓冲区读取字节做准备。
  • rewind():从头再读或再写,limit不变,position设置为0。
  • mark():标记当前的position值,和reset()配合使用。
  • reset():将当前position设为mark标记的值。
  • hasRemaining():position和limit之前是否还有元素。
  • clear():清空整个缓冲区(没有擦除)。 position的值设为0, limit的值设为capacity,mark的值被丢弃。为把字节写到缓冲区做准备。
  • compact():只清空已经读过的数据(没有擦除)。未读数据复制到缓冲区的起始处,position设到最后一个未读数据后。

Buffer的分配:要想获得一个Buffer对象首先要进行分配。 每一个Buffer类都有一个静态 allocate(int) 方法。

写数据到Buffer 有两种方式:

  • 从 Channel 写到 Buffer。
  • 通过 Buffer 的 put() 方法写到 Buffer 里。

从Buffer中读取数据 有两种方式:

  • 从Buffer读取数据到Channel。
  • 使用get()方法从Buffer中读取数据。

equals(),当满足下列条件时,表示两个Buffer相等:

  1. 有相同的类型(byte、char、int等)。
  2. Buffer中剩余的byte、char等的个数相等。
  3. Buffer中所有剩余的byte、char等都相同。

compareTo(),比较两个同类型Buffer的剩余元素, 如果满足下列条件,则认为一个Buffer“小于”另一个Buffer:

  1. 第一个不相等的元素小于另一个Buffer中对应的元素 。
  2. 所有元素都相等,但第一个Buffer比另一个先耗尽(第一个Buffer的元素个数比另一个少)。
ByteBuffer

ByteBuffer 是唯一直接与通道交互的缓冲器。

静态方法:

  • ByteBuffer wrap(byte[] array):使用“支持”数组初始化一个 ByteBuffer,数组的和缓存器的数据相互关联。

实例方法:

  • asXXBuffer 系列方法可以获得特定基本数据类型的视图。ByteBuffer 依然是实际存储数据的地方。
  • slice() 创建新的 ByteBuffer 对象,和原来对象的字节数据相互关联,它们的区别是指针对象相互独立。


2. Charset

把字符集包装为对象,提供字符集的编码器和解码器。

Charset.forName("UTF-8").encode("Hello World!");


3. Channel

Java NIO 的通道类似流,但又有些不同:

  1. 既可以从通道中读取数据,又可以写数据到通道。但流的读写通常是单向的。
  2. 通道可以异步地读写。
  3. 通道中的数据总是要先读到Buffer,或者总是要从Buffer中写入。

主要的通道实现:

  • FileChannel 从文件中读写数据,它必须阻塞,不能用在非阻塞模式中。
  • DatagramChannel 能通过UDP读写网络中的数据。
  • SocketChannel 能通过TCP读写网络中的数据。
  • ServerSocketChannel 可以监听新进来的TCP连接,像Web服务器那样。对每一个新进来的连接都会创建一个SocketChannel。
a. FileChannel

创建:

无法直接打开一个FileChannel,需要通过 InputStream、OutputStream 或 RandomAccessFile 的 getChannel 方法来获取一个 FileChannel 实例。

FileChannel 常用方法:

  • read(ByteBuffer),从文件通道读取数据到ByteBuffer,-1 表示已经到达输入的末尾。
  • write(ByteBuffer),从字节缓存区写到文件通道。
  • close(),关闭。
  • transferFrom(),将数据从源通道传输到FileChannel中 toChannel.transferFrom(position, count, fromChannel);
  • transferTo(),将数据从FileChannel传输到其他的channel中 fromChannel.transferTo(position, count, toChannel);

FileChannel其它方法:

  • position() 获取当前位置
  • position(int) 设置当前位置
  • size() 返回该实例所关联文件的大小
  • truncate(int) 截取文件的前int个字节
  • force(boolean) 将通道里尚未写入磁盘的内存缓存数据强制写到磁盘上,boolean指明是否同时将文件元数据(权限信息等)写到磁盘上

Scattering Reads,数据从一个channel读取到多个buffer中。不适用于动态消息(消息大小不固定)。

    ByteBuffer header = ByteBuffer.allocate(128);
    ByteBuffer body   = ByteBuffer.allocate(1024);
    ByteBuffer[] bufferArray = { header, body };
    channel.read(bufferArray);

Gathering Writes 是指数据从多个buffer写入到同一个channel。能较好的处理动态消息。

    ByteBuffer header = ByteBuffer.allocate(128);
    ByteBuffer body   = ByteBuffer.allocate(10
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值