首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

NIO学习系列:缓冲区内部兑现机制

2012-10-28 
NIO学习系列:缓冲区内部实现机制接上一篇NIO学习系列:核心概念及基本读写,本文继续探讨和学习缓冲区的内部

NIO学习系列:缓冲区内部实现机制


接上一篇NIO学习系列:核心概念及基本读写,本文继续探讨和学习缓冲区的内部实现机制。

5.??? 缓冲区内部实现
?? 从上面对NIO的学习中,我们知道每一个缓冲区都有复杂的内部统计机制,它会跟踪已经读了多少数据以及还有多少空间可以容纳更多的数据,以便我们对缓冲区的操作。在本节我们就将学习NIO的两个重要的缓冲区组件:状态变量和访问方法。虽然NIO的内部统计机制初看起来可能很复杂,但是您很快就会看到大部分的实际工作都已经替您完成了。您只需像平时使用字节数组和索引变量一样进行操作即可。


?? 1)??? 状态变量:
?? 状态变量是前一节中提到的"内部统计机制"的关键。 每一个读/写操作都会改变缓冲区的状态。通过记录和跟踪这些变化,缓冲区就可能够内部地管理自己的资源。
?? 每一种Java基本类型的缓冲区都是抽象类Buffer的子类,从Buffer的源代码中可以发现,它定义了三个私有属性:


      ?? 回想一下 ,limit决不能大于capacity,此例中这两个值都被设置为8。我们通过将它们指向数组的尾部之后(第8个槽位)来说明这点。
      NIO学习系列:缓冲区内部兑现机制
      ?? 我们再将position设置为0。表示如果我们读一些数据到缓冲区中,那么下一个读取的数据就进入 slot 0。如果我们从缓冲区写一些数据,从缓冲区读取的下一个字节就来自slot 0。position设置如下所示:
      NIO学习系列:缓冲区内部兑现机制
      ?? 由于缓冲区的最大数据容量capacity不会改变,所以我们在下面的讨论中可以忽略它。

      ?? 第一次读取:
      ?? 现在我们可以开始在新创建的缓冲区上进行读/写操作了。首先从输入通道中读一些数据到缓冲区中。第一次读取得到三个字节。它们被放到数组中从position开始的位置,这时position被设置为0。读完之后,position就增加到了3,如下所示,limit没有改变。
      NIO学习系列:缓冲区内部兑现机制

      ?? 第二次读取:
      ?? 在第二次读取时,我们从输入通道读取另外两个字节到缓冲区中。这两个字节储存在由position所指定的位置上, position因而增加2,limit没有改变。
      NIO学习系列:缓冲区内部兑现机制

      ?? flip:
      ?? 现在我们要将数据写到输出通道中。在这之前,我们必须调用flip()方法。 其源代码如下:

        ?? 我们现在可以将数据从缓冲区写入通道了。position被设置为0,这意味着我们得到的下一个字节是第一个字节。limit已被设置为原来的position,这意味着它包括以前读到的所有字节,并且一个字节也不多。

        ?? 第一次写入:
        ?? 在第一次写入时,我们从缓冲区中取四个字节并将它们 写入输出通道。这使得position增加到4,而limit不变,如下所示:

        NIO学习系列:缓冲区内部兑现机制


        ?? 第二次写入:
        ?? 我们只剩下一个字节可写了。limit在我们调用flip()时被设置为5,并且position不能超过limit。 所以最后一次写入操作从缓冲区取出一个字节并将它写入输出通道。这使得position增加到5,并保持limit不变,如下所示:
        NIO学习系列:缓冲区内部兑现机制

        ?? clear:
        ?? 最后一步是调用缓冲区的clear()方法。这个方法重设缓冲区以便接收更多的字节。其源代码如下:

          ?

          ?? 2)??? 访问方法:
          ?? 到目前为止,我们只是使用缓冲区将数据从一个通道转移到另一个通道。然而,程序经常需要直接处理数据。例如,您可能需要将用户数据保存到磁盘。在这种情况下,您必须将这些数据直接放入缓冲区,然后用通道将缓冲区写入磁盘。 或者,您可能想要从磁盘读取用户数据。在这种情况下,您要将数据从通道读到缓冲区中,然后检查缓冲区中的数据。
          ?? 实际上,每一个基本类型的缓冲区都为我们提供了直接访问缓冲区中数据的方法,我们以ByteBuffer为例,分析如何使用其提供的get()和put()方法直接访问缓冲区中的数据。

          ?

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

                while?(true)?{???????buffer.clear();???????int?r?=?fcin.read(?buffer?);?????????if?(r==-1)?{?????????break;???????}?????????buffer.flip();???????fcout.write(?buffer?);??}??

              ?? read()和write()调用得到了极大的简化,因为许多工作细节都由缓冲区完成了。clear()和flip()方法用于让缓冲区在读和写之间切换。

热点排行