zoukankan      html  css  js  c++  java
  • 四、Java NIO 缓冲区

    所有文章

    https://www.cnblogs.com/lay2017/p/12901123.html

    正文

    本文继续Java NIO的缓冲区(Buffer)部分。我们前面不断提及的,Buffer将在和Channel打交道的时候使用。我们从Channel读入数据到Buffer,或者从Buffer写入数据到Channel。

    那么Buffer是什么呢?Buffer其实就是一块指定了一定容量大小的内存空间,你可以对Buffer进行数据的读写。你也可以简单理解为定义了一个数组,这个数组被封装到了一个Buffer对象当中,并且提供了一些列的操作方法,使得易于使用。

    Buffer的基本用法

    使用Buffer来读写数据大体要遵循以下4个步骤

    1.将数据写入到Buffer当中

    2.调用Buffer的flip方法,翻转position到0的位置

    3.将从position=0的位置开始从Buffer读取数据

    4.调用Buffer的clear方法或者Buffer的compact方法,将已经读取完的数据进行清理

    当你向一个Buffer读入数据,Buffer会持续跟踪你写入了多少数据。一旦你想要读取数据的时候,你需要将Buffer从写入模式切换到读取模式,因此需要先调用flip方法。

    一旦你读取完了所有的数据,你需要清理Buffer,为再次写入做准备。你可以调用clear或者compact方法。clear方法将清空整个Buffer。compact方法只是清理了你已经读取的那部分数据。未读取的那部分,将被移到Buffer的开始位置,数据的写入将从未读取数据的最后一个位置的下一个位置开始。

    下面是一个Buffer的使用示例,包含了write、flip、read、clear操作

    // 构建文件对象
    RandomAccessFile aFile = new RandomAccessFile("data/nio-data.txt", "rw");
    // 获取通道
    FileChannel inChannel = aFile.getChannel();
    //分配一个48字节的缓冲区
    ByteBuffer buf = ByteBuffer.allocate(48);
    // 从通道读取数据到缓冲区
    int bytesRead = inChannel.read(buf);
    // 当数据不为空
    while (bytesRead != -1) {
      // 翻转position=0,进入读取模式,从0开始读取数据
      buf.flip();
      // 当Buffer还有剩余数据的时候
      while(buf.hasRemaining()){
          // 读取并打印数据
          System.out.print((char) buf.get());
      }
      // 清空整个Buffer,准备写入
      buf.clear();
      // 再次从通道读取数据到Buffer
      bytesRead = inChannel.read(buf);
    }
    // 关闭文件对象
    aFile.close();

    Buffer的capacity、position、limit

    一个Buffer是一个内存空间,你可以对它进行数据的读写。这块内存空间封装成了一个Buffer对象,并提供一些方便的操作方法使得它易于使用。

    Buffer主要有三个属性你必须知道的:

    1.capacity:容量

    2.position:位置

    3.limit:限制

    position和limit的值取决于当前是读取模式还是写入模式。capacity总是从头到尾保持不变,无论是读取还是写入模式。

    下图是两种模式写,这三个值对应的示例

     Capacity

    作为一个内存空间,一个Buffer会有一个固定的大小,我们也叫做容量"capacity"。Buffer的最大空间是由capacity来确定的,如果你想要不断写入数据,你就需要不断clear调用Buffer中旧的数据,也就是为什么每次write到Buffer的时候要clear或者compact。

    Position

    当你想要对Buffer写入数据的时候,你是在一个确定的位置(position)上操作的,可以理解为数组的索引。在Buffer初始化的时候,position=0.当数据被写入到Buffer以后,position将会不断变化,指向下一个位置,不过position总是小于等于capacity-1

    当你想要从Buffer读取数据的时候,也一样是从position的位置开始读取的,所以你需要调用flip将position=0。

    Limit

    在写入模式中,limit表示当前你可以写入Buffer的最大空间。limit总是等于capacity。

    当你在读取模式的时候,调用了flip之后。在设置position=0之前会先把limit=position。这意味着你可以从position=0开始读取数据,直到limit前的数据。也就是说,之前写入了多少数据,这里就读取多少数据。

    Buffer的类型

    Java NIO的Buffer主要有以下几种类型

    1.ByteBuffer

    2.MappedByteBuffer

    3.CharBuffer

    4.DoubleBuffer

    5.FloatBuffer

    6.IntBuffer

    7.LongBuffer

    8.ShortBuffer

    如你所见,以上的Buffer基本上就是对应了各种基本数据类型。MappedByteBuffer特殊一点,后续文章将会单独说明

    创建一个Buffer

    获取一个Buffer对象,其实就是分配一块内存空间。每一个Buffer实现类会有一个allocate方法来创建Buffer对象。

    ByteBuffer buf = ByteBuffer.allocate(48);
    CharBuffer buf = CharBuffer.allocate(1024);

    写入数据到Buffer

    写入数据到Buffer中有两种方式

    1.从Channel写入数据到Buffer

    int bytesRead = inChannel.read(buf);

    2.调用put方法自己写入数据到Buffer

    buf.put(127); 

    flip

    flip方法将Buffer从write模式切换到了read模式。调用flip方法position将设置为0,limit将设置为之前position所在的位置。

    换句话说,position指定了从哪里开始读取数据,limit指定了你可以读取多少数据。

    从Buffer读取数据

    同样有两种方式从Buffer读取数据

    1.从Buffer写入到Channel中

    int bytesWritten = inChannel.write(buf);

    2.从Buffer读取数据,通过get方法

    byte aByte = buf.get();

    rewind

    rewind方法和flip方法类似,都是将position设置为0。但是rewind方法不影响limit的值,因此,如果你flip后读取了一次,想再读取一次。你可以使用rewind设置为0,重新读取。

    clear和compact

    一旦你从Buffer读取完了数据,你需要让Buffer可以再次写入。这时候你要调用clear或者compact方法。

    如果你调用clear方法,position设置为0,limit设置为capacity。换句话说,Buffer是cleared状态,但是Buffer中的数据并没有清空。同时要注意,clear方法不管你是不是读取了Buffer中的所有数据,直接设置position=0,因此未读完的数据将被忽略。

    如果你不想未读取完的数据被忽略,那么你需要调用compact方法,而不是clear方法。

    compact方法会把未读取的数据拷贝到Buffer开始的位置,并设置position等于未读取完的数据的位置的下一个位置。并把limit=capacity,像clear一样。

    调用了clear或者compact以后,Buffer将可以开始写入,Buffer中的数据将被覆盖。

    mark和reset

    如果你想标记position所在的位置,你需要调用mark方法。想要恢复position的位置到mark的位置,调用reset方法

    buffer.mark();
    
    buffer.reset();  //set position back to mark.    

    equals和compareTo

    你可能想要比较两个Buffer

    equals比较相等

    如果满足以下条件则相等

    1.数据类型相等

    2.剩余数据量相等

    3.剩余数据相等

    compareTo比较大小

    如果满足以下条件表示小于

    1.第一个元素的大小更小

    2.元素更少

  • 相关阅读:
    redis哨兵高可用
    数据库主从搭建
    docker 补充
    docker 进阶操作
    docker 简介
    数据可视化(Matplotlib)
    数据操作
    pandas练习
    Pandas简介
    python mysql utf-8 latin
  • 原文地址:https://www.cnblogs.com/lay2017/p/12905616.html
Copyright © 2011-2022 走看看