Buffer类是java.nio的构造基础。一个Buffer对象是固定数量的数据的容器,其作用是一个存储器,或者分段运输区
在这里,数据可以被存储并在之后用于检索。缓冲区可以被
写满或者释放。对于每个非布尔原始数据类型都有一个缓冲区类,即Buffer的子类有: ByteBuffer、CharBuffer、、DoubleBuffer、FloatBuffer、IntBuffer、LongBuffer和ShortBuffer,是没有BooleanBuffer之说的。尽管缓冲区的作用于他们存储的原始数据类型,但缓冲区十分倾向于处理字节。费字节缓冲区可以在后台执行从字节或者到字节的转换,这取决于缓冲区是如何创建的。
缓冲区的四个属性:
所有的缓冲区都具有四个属性来提供关于其所包含的数据元素的信息,这四个属性尽管简单,但是其至关重要,需要熟记于心。
容量(Capacity):缓冲区能够容纳的数据元素的最大数量。这一容量在缓冲区创建时被设定,并且永远不能被改变。
上届(Limit):缓冲区的第一个不能被读或者写的元素,缓冲创建时,limit的容量为 1024,但是从512之后既不能读也不能写,因此可以理解成,Buffer的实际可用大小为512.
位置(Mark):一个备忘位置。标记在设定前是未定义的(undefined),然后buffer.position(6),这时发送给channel的数据就是 6-10的数据。发送完成之后,我们可以调用buffer.reset() 使得 position = mark,因此这里的mark只是用于临时记录一下位置用的。
请切记,在使用Buffer时,我们实际操作的就是这四个属性的值。我们发现,Buffer类并没有包括get()或者put()函数,但是,每一个Buffer的子类都有这两个函数,但他们所采用的参数类型,以及他们返回的数据类型,对于每个子类来说都是唯一的,所以他们不能在顶层Buffer类中被抽象地声明。他们定义必须被特定类型的子类所遵从。若不加以特殊说明,我们在下面讨论的一些内容,都是以ByteBuffer为例,当然,它有get和put的方法。
相对存取和绝对存取:
可以用下面的代码来测试一下 ByteBuffer中的 capacity、limit、position 这些方法:
public class BufferProgram {
public static void main(String args[]) throws Exception {
//这用用的是文件IO处理
FileInputStream fin = new FileInputStream("E:/GP_WORKSPACE/test.txt");
//创建文件的操作管道
FileChannel fc = fin.getChannel();
//分配一个10个大小缓冲区,说白了就是分配一个10个大小的byte数组
ByteBuffer buffer = ByteBuffer.allocate(10);
output("初始化", buffer);
buffer.put("xsd".getBytes());
//先读一下
fc.read(buffer);
output("调用read()", buffer);
//准备操作之前,先锁定操作范围
buffer.flip();
output("调用flip()", buffer);
//判断有没有可读数据
while (buffer.remaining() > 0) {
byte b = buffer.get();
output("调用get()", buffer);
// System.out.print(((char)b));
}
output("调用get()", buffer);
//可以理解为解锁
buffer.clear();
output("调用clear()", buffer);
//最后把管道关闭
fin.close();
}
//把这个缓冲里面实时状态给答应出来
public static void output(String step, Buffer buffer) {
System.out.println(step + " : ");
//容量,数组大小
System.out.print("capacity: " + buffer.capacity() + ", ");
//当前操作数据所在的位置,也可以叫做游标
System.out.print("position: " + buffer.position() + ", ");
//锁定值,flip,数据操作范围索引只能在position - limit 之间
System.out.println("limit: " + buffer.limit());
System.out.println();
}
}
根据上面的代码看出,当执行put方法的时候,是在向容器当中增加值,调用read方法的时候,会把当前的position这个下标值置为当前的字节数。
调用flip方法之后,buffer的limit的值被重新确定成position的当前值,position重新变成0,并且不可变,然后每次调用一次get方法都会使得 position向后增加1,直到position
与limit相等。