NIO学习笔记三

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lzx_longyou/article/details/51969158

缓冲区内部细节

    NIO中有两个重要的缓冲区组件:状态变量和访问方法。

    每一个读写操作都会改变缓冲区的状态,状态变量用于记录和跟踪这些变化,使得缓冲区内部可以管理自己的资源。

    访问方法涉及对缓冲区内数据的访问,包括将数据放入缓冲区,从缓冲区中获取数据进行查看。

状态变量

     有三个值用来指定缓冲区在任意时刻的状态:

  • position
  • limit
  • capacity

Position

    在从通道读取时,position变量跟踪已经写了多少数据,它指向的是下一个字节将要放到数组的哪一个元素中。比如,有一个长度为10的字节数组,一开始position指向的是数组下表为0的位置,如果从通道中读取了三个字节放到缓冲区中,position会往后移动,其值将设置为3,指向数组中第四个元素。

    在写入通道时,若从缓冲区中获取数据,position值跟踪从缓冲区获取了多少数据,它指向下一个字节来自数组的哪一个元素。比如,从缓冲区写了5个字节到通道中,那么position将被设置为5,指向数组的第六个元素,表示下次写入从这里开始获取数据。

Limit

    在从缓冲区写入通道时,limit变量表明还有多少数据需要取出,在从通道读入缓冲区时,limit变量表欧明还有多少空间可以放入数据。position总是小于等于limit

Capacity

    缓冲区的 capacity 表明可以储存在缓冲区中的最大数据容量。实际上,它指定了底层数组的大小, 或者至少是指定了准许我们使用的底层数组的容量。limit 决不能大于 capacity。

三者的关系是:position <= limit <= capacity

观察变量的移动

    新建一个缓冲区,假设这个缓冲区的总容量为8个字节,那么Buufer的状态如下:

         

    上图中,Position指向数组下标为0的位置,此时position的值为0,limit和capacity指向数组最后一个元素的下一个位置,此时他们的值为8,因为数组的下标是从0开始的。

第一次读取

      从输入通道中读取三个字节放到缓冲区中,此时position会往后移动三次,指向数组下标为3的元素的位置,表示下一个读取的字节应该放在这里。limit没有改变,如下所示:

                    

第二次读取

    第二次读取两个字节到缓冲区中,position继续往后移动两次,指向了第6个数组元素的位置,此时值为5,如下所示:

       

调用filp()函数

    在将数据写到输出通道前,必须先调用flip()方法,该方法做了两件事:

  • 将limit设置成当前position的值,即limit指向当前position指向的位置。
  • 将position设置为0。

          

第一次写入

    从缓冲区中取出四个字节写入输出通道,此时position往后移动四位,值为4,limit不变,如下所示:

             

第二次写入

    第二次把剩下的一个字节取出,写入到输出通道,此时position往后移动一位,值为5,与limit重合,但不超过limit,如下所示:

              

调用clear()方法

    该方法重设缓冲区,做了两件事情:

  • 它将limit设置与capacity相同。
  • 它设置position为0。

    调用clear()之后的状态如下图:

       

访问方法

在缓冲区中,可以使用get()和put()方法直接访问缓冲区中的数据。

get()方法

ByteBuffer 类中有四个 get() 方法:

byte get();
ByteBuffer get( byte dst[] );
ByteBuffer get( byte dst[], int offset, int length );
byte get( int index );

需要注意的是,前三个get()方法是相对的,最后一个方法是绝对的。相对意味着 get() 操作服从 limit 和 position 值。更明确地说,字节是从当前 position 读取的,而 position 在 get 之后会增加。另一方面,一个绝对方法会忽略 limit 和 position 值,也不会影响它们。

put()方法

ByteBuffer 类中有五个 put() 方法:

ByteBuffer put( byte b );
ByteBuffer put( byte src[] );
ByteBuffer put( byte src[], int offset, int length );
ByteBuffer put( ByteBuffer src );
ByteBuffer put( int index, byte b );
与 get() 方法一样,我们将把 put() 方法划分为相对或者绝对 的。前四个方法是相对的,而第五个方法是绝对的。

示例

import java.nio.ByteBuffer;

public class TypesInByteBuffer {
	static public void main(String args[]) throws Exception {
		ByteBuffer buffer = ByteBuffer.allocate(64);

		buffer.putInt(30);
		buffer.putLong(7000000000000L);
		buffer.putDouble(Math.PI);

		buffer.flip();

		System.out.println(buffer.getInt());
		System.out.println(buffer.getLong());
		System.out.println(buffer.getDouble());
	}
}


          

猜你喜欢

转载自blog.csdn.net/lzx_longyou/article/details/51969158
今日推荐