网络编程之每天学习一点点[day3]-----java.nio.*Buffer的API操作
发布日期:2021-06-30 13:45:17 浏览次数:2 分类:技术文章

本文共 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 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:网络编程之每天学习一点点[day4]-----nio实现单向通信
下一篇:网络编程之每天学习一点点[day2]-----伪异步IO

发表评论

最新留言

不错!
[***.144.177.141]2024年04月10日 03时45分38秒