Buffer缓冲区
2021-04-14 本文已影响0人
GavinZZW
缓冲区(Buffer):缓冲区本质上是一个可以读写数据的内存块,可以理解成是一个数组,该对象
提供了一组方法,可以更轻松地使用内存块,,缓冲区对象内置了一些机制,能够跟踪和记录缓冲区的
状态变化情况。Channel 提供从网络读取数据的渠道,但是读取或写入的数据都必须经由 Buffer.
![](https://img.haomeiwen.com/i25737031/cea278c178766a3d.png)
Buffer常用API介绍
![](https://img.haomeiwen.com/i25737031/a2f4e6572e30c1e0.png)
在 NIO 中,Buffer是一个顶层父类,它是一个抽象类, 类的层级关系图,常用的缓冲区分别对应
byte,short, int, long,float,double,char 7种.
1.缓冲区对象创建
方法名 | 说明 |
---|---|
static ByteBuffer allocate(长度) | 创建byte类型的指定长度的缓冲区 |
static ByteBuffer wrap(byte[] array) | 创建一个有内容的byte类型缓冲区 |
//1.创建一个指定长度的缓冲区, 以ByteBuffer为例
ByteBuffer byteBuffer = ByteBuffer.allocate(5);
//2.创建一个有内容的缓冲区
ByteBuffer wrap = ByteBuffer.wrap("lagou".getBytes());
2.缓冲区对象添加数据
方法名 | 说明 |
---|---|
int position()/position(intnewPosition) | 获得当前要操作的索引/修改当前要操作的索引位置 |
int limit()/limit(int newLimit) | 最多能操作到哪个索引/修改最多能操作的索引位置 |
int capacity() | 返回缓冲区的总长度 |
int remaining()/booleanhasRemaining() | 还有多少能操作索引个数/是否还有能操作 |
put(byte b)/put(byte[] src) | 添加一个字节/添加字节数组 |
![](https://img.haomeiwen.com/i25737031/75c15752cb373c0f.png)
代码示例
···
public static void main(String[] args) {
//1.创建一个缓冲区
ByteBuffer allocate = ByteBuffer.allocate(10);
System.out.println(allocate.position());//0 获取当前索引所在位置
System.out.println(allocate.limit());//10 最多能操作到哪个索引位置
System.out.println(allocate.capacity());//10 返回缓冲区总长度
System.out.println(allocate.remaining());//10 还有多少个可以操作的个数
System.out.println("----------------");
// 修改当前索引所在位置
//allocate.position(1);
// 修改最多能操作到哪个索引的位置
//allocate.limit(9);
// System.out.println(allocate.position());//1 获取当前索引所在位置
//System.out.println(allocate.limit());//9 最多能操作到哪个索引位置
//System.out.println(allocate.capacity());//10 返回缓冲区总长度
//System.out.println(allocate.remaining());//8 还有多少个可以操作的个数
// 添加一个字节
allocate.put((byte) 97);
System.out.println(allocate.position());//1 获取当前索引所在位置
System.out.println(allocate.limit());//10 最多能操作到哪个索引位置
System.out.println(allocate.capacity());//10 返回缓冲区总长度
System.out.println(allocate.remaining());//9 还有多少个可以操作的个数
System.out.println("----------------");
// 添加一个数组
allocate.put("abc".getBytes());
System.out.println(allocate.position());//4 获取当前索引所在位置
System.out.println(allocate.limit());//10 最多能操作到哪个索引位置
System.out.println(allocate.capacity());//10 返回缓冲区总长度
System.out.println(allocate.remaining());//6 还有多少个可以操作的个数
System.out.println("----------------");
// 添加一个数组
allocate.put("123456".getBytes());
System.out.println(allocate.position());//10 获取当前索引所在位置
System.out.println(allocate.limit());//10 最多能操作到哪个索引位置
System.out.println(allocate.capacity());//10 返回缓冲区总长度
System.out.println(allocate.remaining());//0 还有多少个可以操作的个数
System.out.println(allocate.hasRemaining());//false 是否还能操作
System.out.println("----------------");
//如果缓冲区满了. 可以调整position位置, 就可以重复写. 会覆盖之前存入索引位置的值
allocate.position(0);
allocate.put("123456".getBytes());
System.out.println(allocate.position());//6 获取当前索引所在位置
System.out.println(allocate.limit());//10 最多能操作到哪个索引位置
System.out.println(allocate.capacity());//10 返回缓冲区总长度
System.out.println(allocate.remaining());//4 还有多少个可以操作的个数
System.out.println(allocate.hasRemaining());//true 是否还能操作
}
···
3.缓冲区对象读取数据
方法名 | 说明 |
---|---|
flip() | 写切换读模式 limit设置position位置, position设置0 |
get() | 读一个字节 |
get(byte[] dst) | 读多个字节 |
get(int index) | 读指定索引的字节 |
rewind() | 将position设置为0,可以重复读 |
clear() | 切换写模式 position设置为0 , limit 设置为 capacity |
array() | 将缓冲区转换成字节数组返回 |
flip()方法
![](https://img.haomeiwen.com/i25737031/27612b67a5f63310.png)
clear()方法
![](https://img.haomeiwen.com/i25737031/8ecfac2c50167a50.png)
public static void main(String[] args) {
//1.创建一个指定长度的缓冲区
ByteBuffer allocate = ByteBuffer.allocate(10);
allocate.put("0123".getBytes());
System.out.println("position:" + allocate.position());//4
System.out.println("limit:" + allocate.limit());//10
System.out.println("capacity:" + allocate.capacity());//10
System.out.println("remaining:" + allocate.remaining());//6
//切换读模式
System.out.println("读取数据--------------");
allocate.flip();
System.out.println("position:" + allocate.position());//4
System.out.println("limit:" + allocate.limit());//10
System.out.println("capacity:" + allocate.capacity());//10
System.out.println("remaining:" + allocate.remaining());//6
for (int i = 0; i < allocate.limit(); i++) {
System.out.println(allocate.get());
}
//读取完毕后.继续读取会报错,超过limit值
//System.out.println(allocate.get());
//读取指定索引字节
System.out.println("读取指定索引字节--------------");
System.out.println(allocate.get(1));
System.out.println("读取多个字节--------------");
// 重复读取
allocate.rewind();
byte[] bytes = new byte[4];
allocate.get(bytes);
System.out.println(new String(bytes));
// 将缓冲区转化字节数组返回
System.out.println("将缓冲区转化字节数组返回--------------");
byte[] array = allocate.array();
System.out.println(new String(array));
// 切换写模式,覆盖之前索引所在位置的值
System.out.println("写模式--------------");
allocate.clear();
allocate.put("abc".getBytes());
System.out.println(new String(allocate.array()));
}
注意事项:
- capacity:容量(长度)limit: 界限(最多能读/写到哪里)posotion:位置(读/写
哪个索引) - 获取缓冲区里面数据之前,需要调用flip方法
- 再次写数据之前,需要调用clear方法,但是数据还未消失,等再次写入数据,被覆盖了
才会消失。