一、首先,什么是Buffer?
Buffer,中文意思就是缓冲区,一个用于特定基本类型的容器,由java.nio提供该类,及以下常用子类:
ByteBuffer CharBuffer ShortBufer IntBuffer LongBuffer FloatBuffer DoubleBuffer,并没有BooleanBuffer.
二、其次,这么多的buffer,它的作用是什么呢?
缓冲区buffer主要是和通道数据交互,即从通道中读入数据到缓冲区,和从缓冲区中把数据写入到通道中,通过这样完成对数据的传输。
三、然后,buffer怎么用呢?
要了解buffer的用法,我们需要先了解buffer的几个重要的属性:
capacity:容量,表示buffer的最大数据容量,缓冲区容量不能为负,创建后不能更改
limit:限制,按照索引来,limit之后的数据不可读写,即只有在limit范围内的数据我们才可以读写操作。
position:位置,下一个要读取或写入的索引位置。该位置不能大于limit的限制。
mark::标记,标记后的索引位置,我们可以通过reset方法恢复position到该位置,该mark的位置要小于或等于position
即以上的4个属性满足条件:mark<=position<=limit<=capacity
了解了以上4个属性之后,我们就可以来使用缓冲区了,分为以下几个步骤:
1、建立缓冲区
缓冲区有两种,一种是非直接缓冲区,另一种是直接缓冲区,两种方法根据情景不同在不同的地方使用,下面是它们的创建方式:
ByteBuffer buffer=ByteBuffer.allocate(1024); //非直接 大小为1024个字节 此时它的position=0 limit=1024 capacity=1024
ByteBuffer buf =ByteBuffer.allocateDirect(1024); //直接 大小为1024个字节
2、写入数据
buffer.put("abcde".getBytes()); //将一个字节数组写入缓冲区 此时它的position=5 limit=1024 capacity=1024
//再写一个数组呢??
buffer.put("abcde".getBytes()); //该数组会在之前position开始写 写完后 position=10 limit=1024 capacity=1024
3、读取数据
在读取数据的时候,重要的一步是将缓冲区翻转,即:
buffer.flip(); //这一步的作用是 使position=0 limit为可以操作的最大字节数 这里limit=10 capacity不变 还是1024
可以这样理解,此时你只能操作缓冲区中有数据的那部分 。翻转之后就可以读取了,下面暂时先将它的内容打印出来就好了:
System.out.println(new String(buffer.array(),0,buffer.limit()));
4、clear缓冲区
清空缓冲区,但是注意,缓冲区中的数据并没有被清空,比如输入:
System.out.println(new String(byteBuffer.array(),0,2)); //它的结果在这里是:ab
那么这个方法的作用是什么呢?回到属性,执行下面语句:
System.out.println(byteBuffer.position());
System.out.println(byteBuffer.limit());
System.out.println(byteBuffer.capacity());
输出的结果是(以空格代替换行): 0 1024 1024
也就是说,现在这个缓冲区现在可以从索引0位置开始操作了。那就put试一试:
byteBuffer.put("hhh".getBytes()); //注意这里只put3个字节
那么如果put之后的position、limit、capacity又是多少呢?
此时position=3 limit=1024 capacity=1024
对于上面的结果?也许会有疑问?先保留吧,接下来我们读取该buffer的内容:
byteBuffer.flip(); //读之前先翻转 翻转后position=3 limit=3 capacity=1024
System.out.println(new String(buffer.array(),0,buffer.limit()));
结果是:hhh
不知道小伙伴有没有疑问,不是说之前的数据还在吗?它去哪了呢?
被遗忘了,这里还是要把clear()方法再次提出来,之前说过,它并不会将缓冲区中的数据清空,也就是说缓冲区中之前的数据还在。执行clear后我们可以像操作一个空的缓冲区
一样从索引0位置开始来操作这个缓冲区。但是之前的数据还存在,只是被遗忘了。如果上面我们没有执行byteBuffer.flip(); 那么,结果就会是:hhhdeworld
所以啊,flip()一定不要忘了。
5、其它常用方法
直接缓冲区和非直接缓冲区的使用方法都是按照上面几歩,以下介绍一些其它常用方法:
mark() :标记当前position
reset() :恢复position到mark标记的位置
hasRemaining :判断缓冲区中是否含有元素
get() :从缓冲区中读取单个字节
get(byte[] dst) :批量读取多个字节到dst数组
get(int index) : 读取指定位置的字节(position不会改变)
put(byte b) :将单个字节写入缓冲区position位置
put(byte[] dst) :将多个字节从缓冲区position位置开始写入
put(int index,byte b) : 将指定字节写入缓冲区索引位置,不会移动position
四、总结
buffer的常用方法就是这些了,如有理解不到位的地方还望指正。