Buffer为NIO而生

NIO是jdk1.4后引入,是为了解决普通IO效率慢的问题。NIO将最耗时的IO操作(提取和填充缓冲区)转移回操作系统,让操作系统来完成这个操作因此可以极大的提高效率。NIO是以块为单位处理数据,传统IO是以字节为单位,所以NIO更快。


daemon 操作系统 操作系统nio_添加数据


NIO是通过通道Channel来读取和写入数据的,通道就可以类比传统的IO流,通道是直接和操作系统对接的,我们不会直接从通道中读取和写入数据,而是通过缓冲区Buffer。读取数据时,不会直接从通道中读取数据,而是将数据从通道读入到缓冲区,再从缓冲区拿数据。写数据也一样,通过缓存写入到通道中。

我们首先需要做的就是处理好缓冲区,缓冲区其实就是对数组进行了一定封装,这样整体处理起来比较方便。Java提供的缓冲区类是Buffer,使用时都是使用其子类,比如ByteBuffer,CharBuffer,每种基本数据类型都有其对应的缓冲类型(boolean除外)。

ByteBuffer缓冲区的的三个状态

1)capacity 即容量,也就是缓冲区的大小。它的值是在创建缓冲区的时候指定的,设定后无法对其进行修改。

2)limit 读写限制:也就是缓冲区可以利用(进行读写)的范围的最大值,可以调用ByteBuffer对象的limit(int)方法进行设置,

调用ByteBuffer对象的limit()获取缓冲区读写限制的大小;在刚开始创建缓冲区的时候limit的大小等于capacity。

3)position 读写位置:表示当前进行读写操作时的位置,初始化为0,即缓冲区开始读或者写数据的位置。

可以通过调用ByteBuffer对象的positon(int)方法设置它的值,通过position()可以获取它的值

这三个状态的数值满足一下关系:

0=

在初始化缓冲区的情况下,

position=0;
limit = capacity

添加和读取数据

缓冲区是通过put或者putXXX来向缓冲区添加数据,也可以通过put(index,vlaue)方法在指定的position和limit之间指定的地方添加数据;

通过get()或者getXXX()来获取数据,也可以通过get(int index)方法来获取position到limit之间指定的数据。

注意position的位置会随着数据的写入而移或者读取一个字节一个字节的移动(比如添加一个byte类型的数据position会+1,

添加一个int类型的数据position会+4;),直到position=limit为止。如果position==limit时,再添加数据会报java.nio.BufferOverflowException、再获取数据会报java.lang.IndexOutOfBoundsException。正因为向缓冲区添加数据的时候写数据的时候position会变化,如果想获取缓冲区的数据直接调用get等相关方法获取数据是肯定不行的,

因为此时数据在缓冲区存在数据的部分是0~~position之间,而读数据开始的位置position在此区间之外。

所以要获取此区间的数据需要重新设置position的位置,ByteBuffer提供了一个flip方法,

该方法主要进行两部操作 limit = position;(将limit设为当前position) position =0;

此时通过get方法就可以获取到0到limit之间的数据了

属性介绍

final byte[] hb; final int offset; private int mark = -1; private int position = 0; private int limit; private int capacity;

capacity

缓冲区能够容纳的数据元素的最大数量。这个容量在缓冲区创建时被设定,不能为负并且永远不能被改变。

limit

第一个不应该读取或写入的元素的索引,即执行get()、put操作数据范围不可超过limit值。缓冲区的限制不能为负,并且不能大于其容量。

position

下一个要读取或写入的元素的索引。缓冲区的位置不能为负,并且不能大于其限制。

mark

用于备份当前的position。调用mark( )把当前的position赋值给mark,mark=postion。调用reset( )把mark值还原给position,position=mark。标记在设定前是未定义的默认:-1。结合reset(),mark将会跳转到上次标记的位置,循环的读取内容。

这四个属性之间总是遵循以下关系: 0 <= mark <= position <= limit <= capacity

allocate

初始化字节数组hd,在虚拟机堆上申请内存空间,分配一个新的字节缓冲区(HeapByteBuffer)。新缓冲区的位置(position)将为零,其界限(limit)将为其容量(capacity),其标记(mark)默认:-1。它将具有一个底层实现数组,且其数组偏移量将为零。