前篇可知Buffer是和Chanel配套使用的,Chanel从Buffer中读数据,将数据写入Buffer.Buffer的实质是块内存,被包装成JAVA Object并提供基础方法使我们可以更简单的使用。
熟悉一下三个属性有助于我们理解Buffer是怎样工作的:
- capacity 容量
- position 位置
- limit 界限
这三个属性的在Buffer读和写模式下的意义如图:
Buffer capacity, position and limit in write and read mode. |
Capacity
Buffer是一块内存,其有固定的大小,我们将这个大小表示为Capacity 我们只能写入这个大小的数据进来,如果Buffer满了,我们必须通过read或者clear方法清空空间才能继续写入。
Position
将数据写入Buffer时,positiion会被初始化为0,随后每写入一位+1,最大可以达到capacity-1的位置。我们可以使用filp方法将Buffer从写模式转为读模式,此时每读出一位+1;
Limit
写模式时,Limit表示我们可以写入多少位数据,此时这个值与capacity值是相当的。
读模式时,该值表示我们可以读多少位数据,当我们将写模式转为读模式时,limit值会被设为当时的position值。
有很多种Buffer实现,如下:
- ByteBuffer
- MappedByteBuffer
- CharBuffer
- DoubleBuffer
- FloatBuffer
- IntBuffer
- LongBuffer
- ShortBuffer
我们可以使用如下的allocate方法获得一个Buffer对象并为其分配内存空间
ByteBuffer buf = ByteBuffer.allocate(48);
写入Buffer
有两种方法
- 使用Chanel写入
- 使用Buffer的put方法
法一,将Chanel(数据源)中的数据读入Buffer(缓存区
int bytesRead = inChannel.read(buf); //read into buffer.
法二,调用put方法,该方法有多种变种
buf.put(127);
flip()
如上文所述,filp()方法可以让Buffer从写模式转为读模式,也就是将limit位置设为position位置,将position位置置0.然后我们就可以从position位置开始读Buffer。
读出Buffer
同样有两种方法
- 将Buffer数据读入Channel
- 调用Buffer自带的get方法
法1:将Buffer数据读出到channel中(对于channel来说是写入channel,对Buffer当然是读出)
//read from buffer into channel. int bytesWritten = inChannel.write(buf);
法2:get方法,该方法有多种变种
byte aByte = buf.get();
rewind()
将position置0。
clear() and compact()
可以调用clear或者compact方法来清空Buffer。
clear方法:position置0,limit置于capacity值。也就是回到Buffer刚分配的状态。
compact方法:如果还有未读的数据在Buffer中,将这些未读数据移至Buffer起点,将position放在最后一个未读数据后面,这样写新数据时就不会覆盖旧数据。
mark() and reset()
实际上buffer中还有一个临时标记位变量mark,mark的值必须小于或等于position。mark方法可以将mark值设为position值,调用reset方法可以将position值回复到标记的位置(也就是mark值)
buffer.mark(); //call buffer.get() a couple of times, e.g. during parsing. buffer.reset(); //set position back to mark.
equals() and compareTo()
equal的要求是Buffer同类,Buffer大小相等,Buffer内全部元素相等。
compareTo,逐一比较Buffer内元素大小,如果比不出来就看哪个Buffer先取光元素