美文网首页
Netty之ByteBuffer属性( limit,capaci

Netty之ByteBuffer属性( limit,capaci

作者: 你弄啥来 | 来源:发表于2018-12-18 22:53 被阅读0次

什么是ByteBuffer?

Netty是通过Channel接收和发送数据的,Channel中的数据即为ByteBuffer(缓冲区),同时采用DIRECT BUFFERS,使用堆外直接内存进行Socket读写,不需要进行字节缓冲区的二次拷贝。

ByteBuffer重要的属性:

capacity:

作为一个内存块,Buffer有固定的大小值,也叫作“capacity”,只能往其中写入capacity个byte、long、char等类型。一旦Buffer满了,需要将其清空(通过读数据或者清楚数据)才能继续写数据。

position:

当你写数据到Buffer中时,position表示当前的位置。出事的position值为0,当写入一个字节数据到Buffer中后,position会向前移动到下一个可插入数据的Buffer单元。position最大可为capacity-1。当读取数据时,也是从某个特定位置读,讲Buffer从写模式切换到读模式,position会被重置为0。当从Buffer的position处读取一个字节数据后,position向前移动到下一个可读的位置。

limit:

在写模式下,Buffer的limit表示你最多能往Buffer里写多少数据。 写模式下,limit等于Buffer的capacity。当切换Buffer到读模式时, limit表示你最多能读到多少数据。因此,当切换Buffer到读模式时,limit会被设置成写模式下的position值。换句话说,你能读到之前写入的所有数据(limit被设置成已写数据的数量,这个值在写模式下就是position)

代码演示:

public static void main(String[] args) throws IOException {
  RandomAccessFile ram = new RandomAccessFile("E:\\aaa.txt", "r");
        FileChannel fileChannel = ram.getChannel();//FileChannel是处理文件的channel 相比IO 这个比较简单
        ByteBuffer rendBuffer = ByteBuffer.allocate(1024);//ByteBuffer 刚被创建的时候 position为 0 limit就是 capacity
        bufferPosition("初始化ByteBuffer的时候",rendBuffer);
        int characters = fileChannel.read(rendBuffer);//将channel中的数据读到buffer的时候 position 就是文件的字符数 limit 仍然是capacity
        bufferPosition("从chanel中读到buffer的时候",rendBuffer);
//全部读完之后 limit position capacity的位置
 if (characters > 0) {
      rendBuffer.flip();//调用了一次flip后 position为0 limit为之前position的位置
      bufferPosition("flip之后",rendBuffer);
      byte[] bytes = new byte[rendBuffer.remaining()];
      rendBuffer.get(bytes);//读完之后 此时的position 和limit相等 
  }
   private static void bufferPosition(String desc,ByteBuffer rendBuffer) {
        System.out.println(desc+":     "+"指针现在的位置position  :"+rendBuffer.position()+"容量capacity 
 "+rendBuffer.capacity()+"   limit"+rendBuffer.limit());
    }

}

因为ByteBuffer中的数据是一个连续的byte类型数组,所以我们也可以一个个的读取,可以发现position的值一直在改变

 rendBuffer.flip(); //flip()方法是让position=0,limit=position,mark=-1
  while (rendBuffer.hasRemaining()){
                byte b = rendBuffer.get();
                System.out.println((char)b);
                bufferPosition("一个一个读的时候",rendBuffer);
      }

ByteBuffer常用的API

rewind()

rewind()方法:Buffer.rewind()方法将position设置为0,使得可以重读Buffer中的所有数据,limit保持不变。(ByBuffer中的数据不是读完就没了,可以重复读哦)

clear()和capacity()

clear方法:position将被设置为0,limit设置为capacity的值。
compact()方法:将所有未读的数据拷贝到Buffer起始处,然后将position设置到最后一个未读元素的后面,limit属性依然设置为capacity。可以使得Buffer中的未读数据还可以在后续中被使用。

compact()方法代码演示

 rendBuffer.flip();
//数据不读完调用compact()时
  for(int i=0;i<5;i++){
        byte b = rendBuffer.get();
        System.out.println((char)b);
    }
bufferPosition("一次没有读完之后",rendBuffer); 
rendBuffer.compact();// 将position的值为 limit-(当前的)position
                                    // limit设置成capactiy 可以使得Buffer中的未读数据还可以在后续中被使用。(可以理解为将之前没有读完的数据又重新写了一遍)
  bufferPosition("调用了compact之后",rendBuffer);
  rendBuffer.flip();//这个时候再读的话 limit的就是剩下的数量 position=0 limit=position (注意这个如果不调用flip()方法时,就会出现从position为limit的位置开始读,所以一旦决定要读数据就要flip()没错的)
  bufferPosition("compact之后再flip",rendBuffer);
  while (rendBuffer.hasRemaining()){
         byte b = rendBuffer.get();
         System.out.println((char)b);
    }

相关文章

网友评论

      本文标题:Netty之ByteBuffer属性( limit,capaci

      本文链接:https://www.haomeiwen.com/subject/jbirkqtx.html