Buffer四个基本属性
1、capacity:能够容纳的最大元素数目,创建时设定并不能更改
2、limit: buffer中有效位置数目
3、position: 下一个读或者写的位置
4、mark: 用于记忆的标志位,配合reset()使用,初始值未设定,调用mark后将当前position设为值
标记、位置、限制和容量值有以下关系:
0 <= 标记 <= 位置 <= 限制 <= 容量
Buffer的操作
1、读取
get(),从当前position位置读取
get(index),从index位置读取,不改变当前position
2、写入
put(byte),在当前position位置填充
put(index,byte),按照绝对位置填充不改变当前position属性
3、flip
将limit设为position, 将position设为0。特别注意,flip()方法会改变limit属性,将limit属性从capacity设置为当前position。两次调用buffer的flip方法,将使得position和limit属性都为0。
4、rewind
与flip()类似,但是仅将position设为0,而不改变limit,通常用于重新读取已经被flip的buffer。
5、clear
将buffer重设为空状态,也就是设置limit=capacity,position=0,以便重复利用。
6、compact
清除已经读过的数据,任何未读的数据都被移到缓冲区的起始处,新写入的数据将放到缓冲区未读数据的后面。即将 position 与 limit之间的数据复制到buffer的开始位置,复制后 position = limit -position,limit = capacity。
7、mark与reset
mark初始是未定义的,调用mark后,将当前position设为mark以便reset时返回。rewind,clear,flip都将丢弃已经创建的mark。调用limit(index),positioon(index),如果index的值小于当前mark,mark也将被丢弃。
8、duplicate与slice
通过duplicate()方法将返回一个新创建的buffer,这个新buffer与原来buffer的视图,一样的capacity,但是有自己的position、limit和mark属性。slice将从原来buffer的当前position开始,并且capacity等于原来Buffer的剩余元素数目,也就是(limit-position)。
下面给出这几个方法的调用时buffer的状态变化
向容量大小为12的buffer中写入helloworld,position发生变化
调用flip,准备读取数据,position和limit发生变化
读取数据的过程中
remaining为0时,说明已经读取完成,此时position和limit重叠。
此时再次调用flip,又可以重新读取
下面clear buffer中的数据,重新写入,此时position为0,limit为capacity
写入字符串javanio
此时可以调用flip读取数据
读取数据
此时可以通过rewind将position置为0,重新从头读取
当读到v的时候,mark一下(此时mark=position),下次可以reset之后重新回到mark的位置
继续读取
此时reset,可以重新回到原先mark的位置
调用compact,将未读的数据拷贝到buffer开始处,然后将position设到最后一个未读元素正后面,limit设置成capacity
这为buffer中的某一情形,下面调用duplicate或者slice,会产生一个buffer的副本。下图为原始的buffer。
调用duplicate,复制出来的buffer其实是一个视图,复制出来的buffer和原来的buffer拥有相同的数据,但是每个buffer都有各自的属性。下图为duplicate buffer。
调用slice,取缓冲区的一部分
以上演示的图片来源于Ron Hitchens撰写的Java Nio这本书的网站。