本文共 3486 字,大约阅读时间需要 11 分钟。
基本使用
Buffer是一个对象,它包含一些要写入或者要读取的数据。
在NIO类库中加入Buffer对象,体现了新库与原来IO的一个重要区别。
在面向流的IO(BIO)中,可以将数据直接写入或者读取到Stream对象中,也就是阻塞式IO。
在NIO中,所有的数据都是用缓冲区处理的(读写),也就是非阻塞IO。
缓冲区实质上是一个数组,通常它是一个字节数组ByteBuffer,也可以使用其他类型的数组。这个数组为缓冲区提供了数据的访问读写等操作属性,如位置pos、容量cap、上限lim等概念。
Buffer类型
我们最常用的就是ByteBuffer,实际上每一种java基本类型都对应了一种缓冲区(除了Boolean类型)。
ByteBuffer
CharBuffer
ShortBuffer
IntBuffer
LongBuffer
FloatBuffer
DoubleBuffer
先看一段代码:
//创建指定长度的缓冲区 IntBuffer buf = IntBuffer.allocate(10); buf.put(13);// position位置:0 - > 1 buf.put(21);// position位置:1 - > 2 buf.put(35);// position位置:2 - > 3 //把位置复位为0,也就是position位置:3 - > 0 buf.flip(); System.out.println("使用flip复位:" + buf); System.out.println("容量为: " + buf.capacity()); //容量一旦初始化后不允许改变(warp方法包裹数组除外) System.out.println("限制为: " + buf.limit()); //由于只装载了三个元素,所以可读取或者操作的元素为3 则limit=3 System.out.println("获取下标为1的元素:" + buf.get(1)); System.out.println("get(index)方法,position位置不改变:" + buf); buf.put(1, 4); System.out.println("put(index, change)方法,position位置不变:" + buf);; for (int i = 0; i < buf.limit(); i++) { //调用get方法会使其缓冲区位置(position)向后递增一位 System.out.print(buf.get() + "\t"); } System.out.println("buf对象遍历之后为: " + buf);
打印:
使用flip复位:java.nio.HeapIntBuffer[pos=0 lim=3 cap=10]容量为: 10限制为: 3获取下标为1的元素:21get(index)方法,position位置不改变:java.nio.HeapIntBuffer[pos=0 lim=3 cap=10]put(index, change)方法,position位置不变:java.nio.HeapIntBuffer[pos=0 lim=3 cap=10]13 4 35 buf对象遍历之后为: java.nio.HeapIntBuffer[pos=3 lim=3 cap=10]
解释:
1 IntBuffer通过allocate静态方法向内存中申请了一个长度为10的数组。
2 IntBuffer通过put(int i);方法放置了三个元素,初始状态下IntBuffer内部的position在下标为0的位置,每当放置一个元素,position下标向后移动1位,加入了三个元素,那么position就是3.如果此时打印IntBuffer实例,结果一定是:
java.nio.HeapIntBuffer[pos=3 lim=3 cap=10]
pos:下标位置
lim:有效元素上限
cap:数组容量,即长度,容量一旦初始化不能再改变
3 通过IntBuffer的flip方法,可以将position的位置变为0,那么基于以上放置的三个元素,打印结果一定是:
java.nio.HeapIntBuffer[pos=0 lim=3 cap=10]
4 get(1)表示获取pos下标为1的元素,根据上面放置顺序就是21,调用get(index)者方法不会改变下标pos的位置。
5 put(index, change)方法,position位置也不变,只是会覆盖下标为index的元素。上边例子中下标为1的位置被覆盖为4.
6 迭代buf.limit(),有效元素上限,通过bug.get()方法每次调用,会使缓冲区pos下标位置向后移动一位。那么上边例子中limit为3,开始pos为0,迭代后打印一定是:
java.nio.HeapIntBuffer[pos=3 lim=3 cap=10]
wrap方法使用
wrap方法会包裹一个数组: 一般这种用法不会先初始化缓存对象的长度,因为没有意义,最后还会被wrap所包裹的数组覆盖掉。 并且wrap方法修改缓冲区对象的时候,数组本身也会跟着发生变化。
int[] arr = new int[]{1,2,5}; IntBuffer buf1 = IntBuffer.wrap(arr); System.out.println(buf1); IntBuffer buf2 = IntBuffer.wrap(arr, 0 , 2); //这样使用表示容量为数组arr的长度,但是可操作的元素只有实际进入缓存区的元素长度 System.out.println(buf2);
打印:
java.nio.HeapIntBuffer[pos=0 lim=3 cap=3]java.nio.HeapIntBuffer[pos=0 lim=2 cap=3]
1 IntBuffer.wrap(int[] array),这种方法包装了一个数组,pos的值是初始位置0,lim值是数组的长度,容量也是数组的长度。
2 IntBuffer.wrap(int[] array,int offset, int length),这种方式是复制了数组中从offset位置开始向后的length个长度。返回的缓冲区实例pos依然是初始0,lim则为length的长度,cap为数组的原始长度。
其他方式
IntBuffer buf1 = IntBuffer.allocate(10); int[] arr = new int[]{1,2,5}; buf1.put(arr); System.out.println(buf1);
打印:
java.nio.HeapIntBuffer[pos=3 lim=10 cap=10]
如果先初始化长度,再通过put(int[] src);的方式,pos的位置就会由数组的元素决定,比如上面放置了3个元素,pos的位置就是3,lim上限的长度由初始的缓冲区数组大小决定为10,容量也是。
复制:
//一种复制方法 IntBuffer buf3 = buf1.duplicate(); System.out.println(buf3);
打印:
java.nio.HeapIntBuffer[pos=3 lim=10 cap=10]
duplicate()方法复制了原缓冲区。
buf1.flip(); System.out.println(buf1);
可以通过flip方法让pos回到开始0的位置。
java.nio.HeapIntBuffer[pos=0 lim=3 cap=10]
通过buf1.remaining()方法可以得到缓冲区中的有效可读数组个数。
可读数据为:3
填充数组:
int[] arr2 = new int[buf1.remaining()]; //将缓冲区数据放入arr2数组中去 buf1.get(arr2); for(int i : arr2){ System.out.print(Integer.toString(i) + ","); }
可以通过buf1.get(int[] dst);方式将buf1的数据填充给数组arr2.
转载地址:https://jeffsheng.blog.csdn.net/article/details/80727470 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!