ByteBuffer是Java的NIO使用中最常用的缓冲区,它继承自Buffer是一个抽象类,在通过ByteBuffer.allocate(int capacity)创建时实则创建的是一个HeapByteBuffer,而这个HeapByteBuffer则是ByteBuffer的具体实现类.ByteBuffer内部还是通过数组进行数据的存放
Buffer中关键的四个属性
0<=mark<=position<=limit<=capacity
mark
:上次标记的位置
position
:当前指向的位置
limit
:操作极限位置
capacity
:初始容量,一旦指定不可更改(就是指定的内置byte[]的大小)
在初始创建时,mark=-1,position=0,limit=capacity,在get/put操作时position会相应的改变,在标记/重置操作时mark会相应的改变.
get()方法
public ByteBuffer get(byte[] dst,int offset,int length)
此方法就是读取length个字节到dst中从offset开始的位置,查看源码此方法最终调用如下
public ByteBuffer get(byte[] paramArrayOfByte, int paramInt1, int paramInt2)
checkBounds(paramInt1, paramInt2, paramArrayOfByte.length);
if (paramInt2 > remaining())
throw new BufferUnderflowException();
System.arraycopy(this.hb, ix(position()), paramArrayOfByte, paramInt1, paramInt2);
position(position() + paramInt2);
return this;
从方法内部可以看出首先检查各参数,就是通过checkBounds()保证传入的三个值>-1,然后判断缓冲区剩余可读字节数是否满足length个,不足则抛出异常,满足的话则复制指定数目的数据到指定数组dst的指定位置上.最后将当前位置向前移动length个.
此方法使用时注意要length<=remaining()否则就会抛异常
public ByteBuffer get(byte[] dst)f方法使用雷同,实则还是调用的get(byte[] dst,0,dst.length)
put()方法
public ByteBuffer put(byte[] src,int offset, int length)
此方法就是读取源数组src中offset开始的length个字节数据到缓冲区中,查看源码最终调用方法如下
public ByteBuffer put(byte[] paramArrayOfByte, int paramInt1, int paramInt2)
checkBounds(paramInt1, paramInt2, paramArrayOfByte.length);
if (paramInt2 > remaining())
throw new BufferOverflowException();
System.arraycopy(paramArrayOfByte, paramInt1, this.hb, ix(position()), paramInt2);
position(position() + paramInt2);
return this;
其实过程与get基本一直,首先判断参数是否合法即>-1,然后判断剩余空间是否足以接收length个字节数据,否则抛出异常,是则接收数据即将源数组中指定数据copy到内置的数组中去,同时将position位置增加length.
flip()方法
public final Buffer flip()
通常所说的切换到读模式,flip()方法会将limit置为position,position置0,mark置为-1,具体实现如下
public final Buffer flip(){
this.limit = this.position;
this.position = 0;
this.mark = -1;
return this;
clear()方法
public final Buffer clear()
而clear方法则是将position置为0,limit置为capcity,mark置为-1,注意并没有清空数据仍然可以进行读取,具体实现如下
public final Buffer clear(){
this.position = 0;
this.limit = this.capacity;
this.mark = -1;
return this;
mark()方法
public final Buffer mark()
就是记录当前position的位置,具体实现如下
public final Buffer mark()
this.mark = this.position;
return this;
reset()方法
public final Buffer reset()
此方法的目的就是将position的位置重置为上次mark的位置,注意若之前没有mark即mark值为-1时则会抛出异常.具体实现如下
public final Buffer reset()
int i = this.mark;
if (i < 0)
throw new InvalidMarkException();
this.position = i;
return this;
Buffer其实就是是一个容器对象,它包含一些要写入或者刚读出的数据。在NIO中加入Buffer对象,体现了新库与原I/O的一个重要区别。在面向流的I/O中,您将数据直接写入或者将数据直接读到Stream对象中。
在NIO库中,所有数据都是用缓冲区处理的。在读取数据时,它是直接读到缓冲区中的。在写入数据时,它是写入到缓冲区中的。任何时候访问NIO中的数据,您都是将它放到缓冲区中。
readBuffer.clear();
SocketChannel channel = (SocketChannel) key.channel();
//这里执行的是对byteBuffer的写操作
int len = channel.read(readBuffer);
2.当要读的时候,要先执行flip()
this.readB...