JAVA NIO Buffer的学习
JAVA NIO Buffer的学习
定义:缓冲区的工作与通道紧密联系。通道是I/O传输发生时通过的入口,而缓冲区是这些数据传输的来源或目标。简单来说buffer就是一块存储区域,其内部的存储是通过基本类型的数组来实现的。
下图是Buffer类的层次图:
缓冲区基础:概念上,缓冲区是包在一个对象内的基本数据元素数组。Buffer类相比一个简单数组的优点是它将关于数据的数据内容和信息包含在一个单一的对象中。Buffer类以及它专有的子类定义了一个用于处理数据缓冲区的API。
- 属性
缓冲区的四个属性(capacity、limit、position、mark)容量(Capacity) 缓冲区能够容纳的数据元素的最大数量。这一容量在缓冲区创建时被设定,并且永远不能被改变。上界(Limit) 缓冲区的第一个不能被读或写的元素。或者说,缓冲区中现存元素的计数。位置(Position) 下一个要被读或写的元素的索引。位置会自动由相应的get( )和put( )函数更新。标记(Mark) 一个备忘位置。调用mark( )来设定mark = postion。调用reset( )设定position = mark。标记在设定前是未定义的(undefined)。这四个属性之间总是遵循以下关系: 0 <= mark <= position <= limit <= capacity
- 缓冲区API
ByteBuffer allocate(int capacity);
ByteBuffer byteBuffer = ByteBuffer.allocate(10);
新创建的ByteBuffer逻辑视图如下
2.2、填充
byteBuffer.put((byte)'H').put((byte)'E').put((byte)'L').put((byte)'L').put((byte)'O');
五次调用put()之后的缓冲区如图,
在GBK编码中,一个英文字符用一个字节表示,所以存储效果如下,此时mark=-1,position=5,limit=10,capcity=10
2.
3、翻转
Flip()函数将一个能够继续添加数据元素的填充状态的缓冲区翻转成一个准备读出元素的释放状态。
调用flip()方法,切换为读就绪状态
,调用flip()方法后缓冲区如图
2.4、读取
System.out.println((char)byteBuffer.get());
System.out.println((char)byteBuffer.get());
System.out.println((char)byteBuffer.get());
读取后缓存区如图:
2.5、压缩
释放已读数据的空间,准备重新填充缓存区
调用compact方法后,缓冲区如图
注意观察数组中元素的变化,实际上进行了数组拷贝,抛弃了已读字节元素,保留了未读字节元素;
2.6、标记
mark()方法调用时使标记被设为当前位置position的值,reset()函数设置position的值为当前的标记位置mark,
ByteBuffer byteBuffer = ByteBuffer.allocate(10);
byteBuffer.put((byte)'H').put((byte)'E').put((byte)'L').put((byte)'L').put((byte)'O');
byteBuffer.flip();
byteBuffer.position(3).mark().position(5).reset();
System.out.println(byteBuffer.position());
这段代码执行后缓冲区情况如下:
2.7、清除
clear()方法被调用时将清除缓冲区,设置position = 0; limit = capacity; mark = -1;但并没有擦除缓冲区中的数据
ByteBuffer byteBuffer = ByteBuffer.allocate(10);
byteBuffer.put((byte)'H').put((byte)'E').put((byte)'L').put((byte)'L').put((byte)'O');
byteBuffer.flip();
System.out.println((char)byteBuffer.get());
System.out.println((char)byteBuffer.get());
byteBuffer.clear();
System.out.println(byteBuffer.position());
System.out.println(byteBuffer.limit());
这段代码执行后,缓冲区如图
2.8、倒带
rewind()方法将倒带缓冲区,设置position=0,mark=-1,rewind方法可用与重复读写缓冲区。
ByteBuffer byteBuffer = ByteBuffer.allocate(10);
byteBuffer.put((byte)'H').put((byte)'E').put((byte)'L').put((byte)'L').put((byte)'O');
byteBuffer.flip();
System.out.println((char)byteBuffer.get());
System.out.println((char)byteBuffer.get());
byteBuffer.rewind();
这段代码执行后,缓冲区如图
常用的buffer
API就这几个,要想更深刻理解这些API还是阅读源码,然后自己写代码实践下。
参考资料:
《Java NIO》