Buffer是什么
和它的名字一样,Buffer是一个缓冲区,本质上是一块可以写入数据。可以读取数据的内存。在NIO中,Buffer用于和NIO中的各种channel交互。数据可以从channel中读入Buffer,然后从Buffer中写入另一个channel。
Buffer中几个重要的概念
- capacity:容量,指定之后不可变动 
- limit:限制,第一个不应该读取或写入数据的索引,初始时和capacity在一个位置。 
- position:位置,下一个可读取或写入的位置,初始为0,不能为负,且不能大于limit 
举几个例子来说明Buffer运作方式
- 初始时,即刚分配 - 1 - ByteBuffer byteBuffer = ByteBuffer.allocate(48); - 其状态图如下: 

- 当写入几个值时 - 1 
 2
 3
 4- byteBuffer.put((byte)1); 
 byteBuffer.put((byte)2);
 byteBuffer.put((byte)3);
 byteBuffer.put((byte)4);- 状态如下  
- 当写入了数据进入缓冲区时,就可以读取数据,在上面说过,数据写入和读取的下一个位置是position,可是现在position在索引为4(数组下标从0开始,这里缓冲区是一个byte数组)如何读取呢。这里就要介绍一下Buffer缓冲区有两种状态,即读和写,在读的状态下,不能做写入操作,同样在写状态下也不能做读操作,否则缓冲区会数据会被破坏。在buffer中提供了flip()来切换读写状态。当调用flip()函数,缓冲区状态由写入变成读取。  - 可以看到,limit移动到position位置,而position移动到索引0位置。可以从Buffer源码中看到这个操作。 - 1 
 2
 3
 4
 5
 6- public final Buffer flip() { 
 limit = position;
 position = 0;
 mark = -1;
 return this;
 }
- 此时进入读状态开始读取数据,如下图  
- 当读取到一半时,这个时候想写数据怎么办,我们知道flip()函数可以切换读写状态,但是position会从0开始,也就是说我们没有读完的数据会被后来写入的数据覆盖。所以这个时候不能用flip()函数来切换,ByteBuffer提供了另外一个函数compact(),该函数会将未读完的数据复制到索引0位置开始,将position和limit之间的数据依次复制,然后limit移动到capacity位置。如下图  
以ByteBuffer为例写一个Demo
| 1 | public class TestBuffer { | 
运行结果:
| 1 | 第一次读取:1 |