Buffer基础
1. Buffer简介
Java NIO中的Buffer用于和NIO通道进行交互。数据是从通道读入缓冲区,从缓冲区写入到通道中的。 缓冲区本质上是一块可以读写数据的内存。这块内存被包装成NIO Buffer对象,并提供了一组方法,用来方便的访问该块内存。Buffer底层就是一个数组,在NIO库中,所有数据都是用缓冲区处理的。在读取数据时,它是直接读到缓冲区中的; 在写入数据时,它也是写入到缓冲区中的;任何时候访问NIO中的数据,都是将它放到缓冲区中。而在面向流I/O系统中,所有数据都是直接写入或者直接将数据读取到Stream对象中。 在NIO中,所有的缓冲区类型都继承于抽象类Buffer,最常用的就是ByteBuffer,对于Java中的基本类型,基本都有一个具体Buffer类型与之相对应,它们之间的继承关系如下图所示:
2. 读写模式原理
为了记录读写的状态和位置,Buffer类提供三个重要的属性:capacity(容量)、position(读写位置)和limit(读写的限制)。
position和limit的含义取决于Buffer处在读模式还是写模式。不管Buffer处在什么模式,capacity的含义总是一样的,表示buffer的大小容量。需要注意的是一旦Buffer初始化,就不能再改变capacity。 下图为Buffer的初始状态:
2.1 Buffer写模式
- position表示写入数据的当前位置,position的初始值为0,position最大可为capacity–1。
- limit表示可对Buffer最多可以写入多少数据。limit最大等于capacity。
下图表示写入了4个字节后的状态:
2.2 Buffer读模式
- position为0,最大值为limit。
- limit表示Buffer里有多少可读数据量。
flip()
发生后,position切换为读取位置,limit切换为读取限制
2.3 Buffer模式切换
flip()
方法`clear()方法\
compact()`方法都会导致Buffer模式切换:
- 执行
flip()
方法如上读模式。 - 执行
clear()
方法后,如下图可以看到Buffer回到初始状态,也就是写状态: - 执行
compact()
方法,是把未读完的部分向前压缩,然后切换至写模式:
3. Buffer读写操作
3.1 使用Buffer写数据
写数据到Buffer有两种方式:
- 从Channel写到Buffer
- 通过Buffer的
put()
方法写到Buffer里
java
// 从通道里面读数据到Buffer里面
int bytesRead = inChannel.read(buf);
// 通过 put 方法写 Buffer
buf.put(127);
3.2 读数据
从Buffer中读取数据有两种方式:
- 从Buffer读取数据到Channel。
- 使用
get()
方法从Buffer中读取数据。
java
//从 Buffer 读取数据到 Channel
int bytesWritten = inChannel.write(buf);
// 使用get()方法从Buffer中读取数据
byte aByte = buf.get();
// 读取位置1数据
buffer.get(1);
// 读取多个位置数据
int[] posArray = {3,6,7};
IntBuffer subBuffer = buffer.get(posArray);