NIO系列Buffer相关

  
  今天在整理nio相关的知识的时候,突然想到还是把整理的东西写下了,方便今后自己忘记的时候参考。

1.position 位置

  缓冲区中将读取或写入的下一个位置。这个位置从0开始计,最大值等于缓冲区的大小。可以用以下方法获取和设置:

1
2
public final int    position()
public final Buffer position(int newPosition)

2.capacity 容量

  缓冲区可以保存的元素的最大数量。容量值在创建缓冲区的时候设置,之后不能改变。可以用以下方法获取:

1
public final int capacity()

3.limit 限度

  缓冲区中可访问数据的末尾位置。只要不改变限度,就无法去读/写超过这个位置的数据,即使缓冲区的容量再大也没有用。限度可以用以下方法获取和设置:

1
2
public final int    limit()
public final Buffer limit(int newLimit)

4.mark 标记

   缓冲区中的一个指定的索引。通过mark()可以标记设置为当前的位置,调用reset()可以将当前的位置返回到mark的位置:

1
2
public final Buffer mark()
public final Buffer reset()

  因为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
2
public final int remaining()
public final boolean hasRemaining()

10.duplicate()

  复制;经常需要建立缓冲区的副本,从而将相同的信息分发到多个channel,那就需要用到duplicate。这里需要注意一点,duplicate并非建立了副本,而是共享了底层的数据。当修改了一个缓冲区,那么另一个缓冲区中的数据也会被修改,所以这个方法主要使用在只准备读取缓冲区的时候。尽管共享数据,但是初始和复制的缓冲区有着独立的position,limit,capacity。在需要通过多个通道并行传输相同数据的时候,这个方法就很有用了。

1
2
public abstract ByteBuffer duplicate()
//省略其他buffer类型

11.slice()

  分片;分片是上面复制的一个变形。分片也会创建一个新的缓冲区,与原缓冲区共享数据。不过与上面复制不同的是:分片的起始位置 等于 原缓冲区的当前位置, 分片的容量capacity最大不超过原缓冲区的limit。也就是说,分片是原缓冲区的一个子集,只包含从当前位置-> limit 的所有元素。

1
2
public abstract ByteBuffer slice()
//省略其他buffer类型