Buffer 缓冲区
缓冲区其实就是一个容器对象,在NIO 中,所有的数据用缓冲区处理的。在读取数据时,它是直接读取到缓冲区中的,写数据也是直接入到缓冲区。
在NIO 中,每一种基本类型都具有一个对应的缓冲区,最常见的就是ByteBuffer。
通过上面的图可以看出来,每个缓冲区都存在hb 的一个不同类型的数组,这个就是用来存储数据, 在他的父类Buffer 有 mark ,position limit capacity 4个属性值。
这四个的值大小 mark <= position <= limit <= capacity,如果有出现不符合这个的就会抛出异常。
- mark : 表示一个临时存放的下标值(只有调用,mark() 方法时 才会使得 position 的值个mark, 初始值 为 -1)
- position: 指定下一个将要被写入或者读取的元素的位置,它是在get()/put()方法中自动更新的,position 的初始值为0。
- limit : 指定还有多少数据需要取出(在从缓冲区写入通道时),或者还有多少空间可以放入数据。
- capacity: 指定最大的容量。实际上它是指定数组的大小。
package neety.nio.buffer;
import java.nio.IntBuffer;
public class IntBufferDemo {
public static void main(String[] args) {
/* 分配新的int 缓冲区,参数为缓存区的容量
* 新缓冲区的当前位置为0,其界限(限制位置) 为其容量,他具有一个底层实现数组,其数组偏移量为0
* private int mark = -1;
private int position = 0;
private int limit; // 偏移量
private int capacity; // 容器量
* final int[] hb; // Non-null only for heap buffers
* */
IntBuffer buffer = IntBuffer.allocate(8);
for (int i = 0 ; i < buffer.capacity() ; ++i){
int j = 2 * (i +1);
buffer.put(j);
}
// 重新设置该缓冲区,见限制位置(position)设置到当前位置 position ++
buffer.flip();
// 查看当前位置和限制位置之间是否存在元素。
while (buffer.hasRemaining()) {
buffer.mark();
int j = buffer.get();
System.out.println(j+" ");
}
}
}
可以通过下面这个代码仔细的观察 position limit capacity 的三值的变化。 capacity 一般是不变的就是最大容量。主要是观察 position 和limit 的变化
package neety.nio.buffer;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class BufferDemo {
public static void main(String[] args) throws IOException {
//这里用文件I/O处理
FileInputStream fileInputStream = new FileInputStream("H:\\workspace\\Java\\IDEAspaceWork\\Study\\src\\main\\java\\neety\\test.txt");
//创建文件通道
FileChannel fileChannel = fileInputStream.getChannel();
// 分配一个10 大小的缓冲区
ByteBuffer byteBuf = ByteBuffer.allocate(10);
out("初始化",byteBuf);
// 读取buffer
fileChannel.read(byteBuf);
out("读取文件写入通道",byteBuf);
//锁定 limit = position 范围
byteBuf.flip();
out("锁定limit",byteBuf);
// 查看当前位置和限制位置之间是否存在元素。
while (byteBuf.hasRemaining()) {
byte j = byteBuf.get();
System.out.print(((char)j)+" ");
}
System.out.println();
out("获取通道数据后的变化:get()",byteBuf);
byteBuf.clear();
out("clear()",byteBuf);
//关闭通道
fileChannel.close();
}
private static void out(String step, ByteBuffer byteBuf) {
System.out.println(step +": ");
// 容量大小
System.out.println("capacity :"+byteBuf.capacity());
// 读取的位置
System.out.println("position :"+byteBuf.position());
// 锁定值 limit , postion 到 capacity 的范围
System.out.println("limit :" + byteBuf.limit());
System.out.println();
}
}
初始化:
capacity :10 //调用了初始的最大容器是10
position :0
limit :10 // 可以扩张的存入的值也是10
读取文件写入通道:
capacity :10
position :4 // 读取文件过后写入到通道里面区 里面就存在文件中的四个字符
limit :10
锁定limit:
capacity :10
position :0 // 这个时候掉了filp(); 方法就是 position 赋值给limit
limit :4
/**
public final Buffer flip() {
limit = position;
position = 0;
mark = -1;
return this;
}
*/
test
获取通道数据后的变化:get():
capacity :10
position :4
limit :4
/**调用git 方法主要是 对于position的值做++
* final int nextGetIndex() { // package-private
if (position >= limit)
throw new BufferUnderflowException();
return position++;
}
**/
clear():
capacity :10
position :0
limit :10
/** 将capacity 值赋值给limit
*
public final Buffer clear() {
position = 0;
limit = capacity;
mark = -1;
return this;
}
**/
Process finished with exit code 0