今天在整理nio相关的知识的时候,突然想到还是把整理的东西写下了,方便今后自己忘记的时候参考。
1.position 位置
缓冲区中将读取或写入的下一个位置。这个位置从0开始计,最大值等于缓冲区的大小。可以用以下方法获取和设置:
1 | public final int position() |
2.capacity 容量
缓冲区可以保存的元素的最大数量。容量值在创建缓冲区的时候设置,之后不能改变。可以用以下方法获取:
1 | public final int capacity() |
3.limit 限度
缓冲区中可访问数据的末尾位置。只要不改变限度,就无法去读/写超过这个位置的数据,即使缓冲区的容量再大也没有用。限度可以用以下方法获取和设置:
1 | public final int limit() |
4.mark 标记
缓冲区中的一个指定的索引。通过mark()可以标记设置为当前的位置,调用reset()可以将当前的位置返回到mark的位置:
1 | public final Buffer mark() |
因为mark和reset是一个用来回到过去(类似存档和读档)的一个返回操作,所以如果将position设置的低于mark的位置,那么会自动丢弃这个mark,说到这就不得不提一下,读取buffer块 和 inputstream等流 是有一些区别的,读取流中的数据会让流中的数据消失(被取走),而读取缓冲区的数据则不会以任何方式改变缓冲区内的数据。实际上只是向前或向后设置了position,从而可以从缓冲区中某个特定的位置开始读取数据。类似的,程序可以通过调整limit来控制要读取数据的末尾。总之,只有容量是限定的。
5.clear()
clear方法将position设置为0,并且将limit设置为capacity大小,从而将缓冲区“清空”,这样就能完全重新填充缓冲区了。
1 | public final buffer clear() |
需要注意的是,clear并没有删除缓冲区的老数据。这些数据任然存在,可以使用绝对的get方法 或者 重新改变limit和position来进行读取
6.compact()
compact的概念有些复杂,他与上面的clear有些类似,clear通过重置position和limit来使buffer完全“清空”,而compact在清空数据时会“保留”未读取的数据。要知道读取buffer的本质 是读取 position与limit之间的数据,读取一个数据那么position的位置就+1,有点类似指针的意思。在执行compact操作时,position与limit之间如果有数据,那么这些未读的数据会被复制到buffer的开始,然后把段数据后+1的地方作为当前position也就是 position = limit - position。同时 会将limit的限定扩大至buffer的末尾 也就是 limit = capacity。
7.rewind()
将position设置为0,不改变limit。通过重置position来实现重新读取缓冲区
1 | public final Buffer rewind() |
8.flip()
将limit设置为当前的position,position设置为0。通过这样可以通过channel输出buffer中刚刚写入的数据。一般在执行channel.wirte(buffer)之前使用
1 | public final Buffer flip() |
9.remain
有2个方法来返回buffer内的信息,但不改变这些信息。remaining()返回position与limit之间的元素数,告知你是否还有数据未读。如果这个数据大于0,那么hasRemaining()方法返回true,反之亦然。
1 | public final int remaining() |
10.duplicate()
复制;经常需要建立缓冲区的副本,从而将相同的信息分发到多个channel,那就需要用到duplicate。这里需要注意一点,duplicate并非建立了副本,而是共享了底层的数据。当修改了一个缓冲区,那么另一个缓冲区中的数据也会被修改,所以这个方法主要使用在只准备读取缓冲区的时候。尽管共享数据,但是初始和复制的缓冲区有着独立的position,limit,capacity。在需要通过多个通道并行传输相同数据的时候,这个方法就很有用了。
1 | public abstract ByteBuffer duplicate() |
11.slice()
分片;分片是上面复制的一个变形。分片也会创建一个新的缓冲区,与原缓冲区共享数据。不过与上面复制不同的是:分片的起始位置 等于 原缓冲区的当前位置, 分片的容量capacity最大不超过原缓冲区的limit。也就是说,分片是原缓冲区的一个子集,只包含从当前位置-> limit 的所有元素。
1 | public abstract ByteBuffer slice() |