Android NIO 系列教程(三) -- Buffer (ByteBuffer)

系列文章:
Android NIO 系列教程(一) NIO概述
Android NIO 系列教程(二) – Channel
Android NIO 系列教程(三) – Buffer
Android NIO 系列教程(四) – Selector
Android NIO 系列教程(五) – FileChannel
Android NIO 系列教程(六) – SocketChannel
Android NIO 系列教程(七) – ServerSocketChannel
Android NIO 系列教程(八) --NIO简易聊天室

Java NIO中的Buffer用于和NIO通道进行交互。如你所知,数据是从通道读入缓冲区,从缓冲区写入到通道中的。

缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存。这块内存被包装成NIO Buffer对象,并提供了一组方法,用来方便的访问该块内存。

Buffer 基础使用

使用 buffer 进行读写,一般需要以下4个步骤:

  1. 写数据到 buffer
  2. 调用 buffer.flip() 切换模式方法
  3. 从 buffer 读取数据
  4. 调用 buffer.clear() 或者 buffer.compat()方法

当你写数据到 buffer,buffer 将会记录你写入了多少数据,当你需要读取数据,你需要调用 flip() 方法,从写模式切换到 读模式,在读模式下,你可以读取buffer 所有的数据。
当你读完所有数据后,你需要调用清除buffer 的数据,这样才能继续写入。清除有两种方法,调用clear()或者compat() 方法;

  • clear() : clear 方法会清除 buffer 中所有的数据
  • compat() : compat 则是清除你所读过的数据,那些未读取的数据,将会被移动初始位置,当有数据写入时,则在它之后的位置被写入,例子可以参考上面的 fileChannel 。

Buffer 的 Capacity, Position 和 Limit

Buffer 本质上一块你可以写入和读取数据的内存块,这个内存块被包裹成 NIO Buffer 对象,并提供一系列方法,以便我们访问这块内存。

为了数据 Buffer 的原理,我们需要认识它的三个组成部分:

  • capacity
  • position
  • limit

capacity 表示 buffer 的容量,当数据到达buffer的容量大小时,你需要使用 clear 或者 compat 才能继续写入数据;
而 position 和 limit 则取决于 buffer 的模式:

position:

  • 写模式: position 表示当前位置,起始位置为 0,当写入一个 byte,long 数据后,position 会移动对应的字节数,即position会向前移动到下一个可插入数据的Buffer单元,position 的最大值 为 capacity - 1
  • 读模式:postion 表示某个特定位置,当将Buffer从写模式切换到读模式,position会被重置为0. 当从Buffer的position处读取数据时,position向前移动到下一个可读的位置

limit:

  • 写模式:表示可以向 buffer 写入的最大数据,即 limit == capacity
  • 读模式:表示你能读到多少数据;当切换到读模式时,limit 相当于 写模式下的 position;换句话说,写入多少数据 position,你就能读到多少数据 limit

如下图:
在这里插入图片描述

Buffer 的基础数据类型

  • MappedByteBuffer
  • CharBuffer
  • DoubleBuffer
  • FloatBuffer
  • IntBuffer
  • LongBuffer
  • ShortBuffer

这些Buffer类型代表了不同的数据类型。换句话说,就是可以通过char,short,int,long,float 或 double类型来操作缓冲区中的字节。

Buffer 创建

Buffer 的创建有两种方式,,如下:

 // 使用 allocate 创建个 48 个字节的 buffer
  ByteBuffer buf = ByteBuffer.allocate(48);
  // 使用 wrap 创建个 48 个字节的 buffer
  byte[] bytes = new byte[48];
  ByteBuffer buf2 = ByteBuffer.wrap(bytes, 0, bytes.length);

通过 wrap ,我们可以很方便的把 byte 转换成 buffer 去使用,从而拿到数据。

向 Buffer 写数据

向 buffer 写数据有两种方式:

  1. 通过 channel 写数据
  2. 调用 bufffer 的 put 方法

如下:

//通过 channel
int bytesRead = inChannel.read(buf); //read into buffer.
//通过 put
buf.put(127);

put 有很多版本,具体可以参考 javadoc。

flip()

flip 方法,会让 buffer 从写模式切换 读模式,调用 flip ,会把 position 重置为 0,limit 则表示写入多少个字节。

向 Buffer 读数据

向 buffer 读数据也有两种方式:

  1. 通过channel 读数据
  2. 通过 buffer 的 get() 方法
//read from buffer into channel.
int bytesWritten = inChannel.write(buf);
//通过 get
byte aByte = buf.get();    

get 也有很多中方法,比如 getInt 等,具体参考 javadoc。

rewind()

该方法会把 position 重置为0,所以你可以重读所有数据,limit 则不受影响。

clear() and compact()

2.1 已解释,这里就不过多累赘

mark() and reset()

通过调用Buffer.mark()方法,可以标记Buffer中的一个特定position;之后可以通过调用Buffer.reset()方法恢复到这个position。例如:

//表示 position,假如 position为2
buffer.mark();
// 调用 reset 之后,position 不是从0开始,而是从 2
buffer.reset();  

equals() and compareTo()

可以使用equals()和compareTo()方法两个Buffer。
equals()
当满足下列条件时,表示两个Buffer相等:

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

equals只是比较Buffer的一部分,不是每一个在它里面的元素都比较。实际上,它只比较Buffer中的剩余元素。

compareTo()

  1. compareTo()方法比较两个Buffer的剩余元素(byte、char等), 如果满足下列条件,则认为一个
    1. Buffer“小于”另一个Buffer:

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

下一章,我们将学习 selector

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值