Netty ByteBuf

本文是使用Google翻译自: http://netty.io/4.1/api/io/netty/buffer/ByteBuf.html

to see https://blog.csdn.net/mydream20130314/article/details/84481390 , thank you

##类结构
io.netty.buffer
Class ByteBuf

java.lang.Object
io.netty.buffer.ByteBuf
所有实现的接口:
ReferenceCounted,Comparable < ByteBuf >
直接已知子类:
AbstractByteBuf,EmptyByteBuf,SwappedByteBuf

public abstract class ByteBuf
extends Object
implements ReferenceCounted,Comparable < ByteBuf >
零个或多个字节(八位字节)的随机和顺序可访问序列。该接口提供一个或多个原始字节数组(byte[])和NIO缓冲区的抽象视图。

##创建缓冲区

建议使用Unpooled类的方法创建一个新的缓冲区, 而不是调用其实现的构造函数。

##随机访问索引

就像普通的原始字节数组一样,ByteBuf使用 零索引。这意味着第一个字节的索引为0,最后一个字节的索引总capacity - 1。例如,要迭代缓冲区的所有字节,无论内部实现如何,都可以执行以下操作:


	 ByteBuf buffer = ...;
	 for (int i = 0; i < buffer.capacity(); i ++) {
	     byte b = buffer.getByte(i);
	     System.out.println((char) b);
	 }
 

##顺序访问索引

ByteBuf提供两个指针变量来支持顺序读写操作 - 分别readerIndex用于读操作和writerIndex写操作。下图显示了两个指针如何将缓冲区分割成三个区域:

  +-------------------+------------------+------------------+
  | discardable bytes |  readable bytes  |  writable bytes  |
  |                   |     (CONTENT)    |                  |
  +-------------------+------------------+------------------+
  |                   |                  |                  |
  0      <=      readerIndex   <=   writerIndex    <=    capacity

##可读字节(实际内容)

该段是实际数据存储的地方。任何名称以读或跳过开头的操作都可以在当前的readerIndex中获取或跳过数据,并通过读取字节的数量来增加它。如果读操作的参数也是ByteBuf,并且没有指定目标索引,那么指定的缓冲区的writerIndex将会一起增加(也就是参数ByteBuf)。

如果剩下可读的内容还不够,IndexOutOfBoundsException将被抛出。默认值通过wrapped或copied新分配ByteBuf的readerIndex是0。


	//迭代缓冲区的可读字节。
	 ByteBuf buffer = ...;
	 while (buffer.isReadable()) {
	     System.out.println(buffer.readByte());
	 }

##可写字节

该段是一个未定义的空间,需要填充。名称开头为write的任何操作将当前数据写入缓冲区, writerIndex将增加其写入字节数。如果写操作的参数也是ByteBuf,并且没有指定源索引,则指定的缓冲区 readerIndex一起增加。
如果没有足够的可写字节剩余,IndexOutOfBoundsException 则被抛出。默认新分配的缓冲区writerIndex是0。通过wrapped或copied分配的缓冲区writerIndex=capacity。


	//用随机整数填充缓冲区的可写字节。
	 ByteBuf buffer = ...;
	 while (buffer.maxWritableBytes() >= 4) {
	     buffer.writeInt(random.nextInt());
	 }
 

##可舍弃的字节

这个段包含读取操作已经读取的字节。最初,这个段的大小是0,但是随着读操作的执行,它的大小会增加到writerIndex。通过调用discardReadBytes()回收未使用的区域可以丢弃读取的字节,如下图所示:

调用discardReadBytes()之前

  +-------------------+------------------+------------------+
  | discardable bytes |  readable bytes  |  writable bytes  |
  +-------------------+------------------+------------------+
  |                   |                  |                  |
  0      <=      readerIndex   <=   writerIndex    <=    capacity

调用discardReadBytes()之后

  +------------------+--------------------------------------+
  |  readable bytes  |    writable bytes (got more space)   |
  +------------------+--------------------------------------+
  |                  |                                      |

readerIndex (0) <= writerIndex (decreased) <= capacity

请注意,调用discardReadBytes()后不能保证可写字节数据内容。在大多数情况下,可写字节数据将不会被移动,甚至可以根据底层缓冲区实现填充完全不同的数据。

##清除缓冲区索引

调用clear()将可以同时设置readerIndex,writerIndex为0。它不清除缓冲区内容(例如填充0),但只重置两个指针。还请注意,这个操作的语义不同Buffer.clear()。

BEFORE clear()

  +-------------------+------------------+------------------+
  | discardable bytes |  readable bytes  |  writable bytes  |
  +-------------------+------------------+------------------+
  |                   |                  |                  |
  0      <=      readerIndex   <=   writerIndex    <=    capacity

AFTER clear()

  +---------------------------------------------------------+
  |             writable bytes (got more space)             |
  +---------------------------------------------------------+
  |                                                         |
  0 = readerIndex = writerIndex            <=            capacity

##搜索操作

对于简单的单字节搜索,请使用indexOf(int, int, byte)bytesBefore(int, int, byte)bytesBefore(byte)在处理NUL终止字符串时特别有用。对于复杂的搜索,使用forEachByte(int, int, ByteProcessor)ByteProcessor 实施。


		final String v = "safkjhaswororldldworldororldldhellodkhsafhhello";
        final String key="world";
        final ByteBuf buffer = Unpooled.buffer();
        buffer.writeBytes(v.getBytes());
        int index = buffer.forEachByte(new ByteProcessor() {
            byte[] bytes = key.getBytes();
            int index = 0;
            @Override
            public boolean process(byte value) throws Exception {
                if(value==bytes[index]){
                    index++;
                    if (index==bytes.length){
                        return false;
                    }
                }else{
                    index=0;
                    if(value==bytes[index]){
                        index++;
                        if (index==bytes.length){
                            return false;
                        }
                    }else{
                        index=0;
                    }
                }
                return true;
            }
        });
        System.out.println(index);
        Assert.assertEquals(v.indexOf(key)+key.length()-1,index);


##标记并复位

每个缓冲区中有两个标记索引。一个用于存储 readerIndex,另一个用于存储 writerIndex。您可以随时通过调用重置方法重新定位其中一个索引。它的工作方式与标记和重置方法类似,InputStream除了没有 readlimit。

##派生缓冲区

您可以通过调用以下方法之一来创建现有缓冲区的视图:

duplicate()共享数据缓冲区,独立维护readerindex和writerindex
slice()共享数据缓冲区中可读的一部分,独立维护readerindex和writerindex
slice(int, int)共享数据缓冲区中可读的一部分,独立维护readerindex和writerindex
readSlice(int) read表示会增加源ByteBuf的readerindex
retainedDuplicate() retained 表示会增加引用计数
retainedSlice()
retainedSlice(int, int)
readRetainedSlice(int)

衍生缓冲器将有一个独立的readerIndex, writerIndex并且标记索引,而这股其他内部数据表示,就像一个NIO缓冲器一样。
如果需要现有缓冲区的全新副本,请调用copy()方法。

##非保留和保留的派生缓冲区

需要注意的是duplicate(),slice(),slice(int, int)并且readSlice(int)不调用retain()上返回的派生缓冲,因而其引用计数将不会增加。如果你需要创建一个增加引用计数派生缓冲,可以考虑使用retainedDuplicate(), retainedSlice(),retainedSlice(int, int)和readRetainedSlice(int)它可能返回产生较少的垃圾一个缓冲区实现。

##转换到现有的JDK类型

###字节数组

如果ByteBuf由字节数组(即byte[])支持,则可以通过该array()方法直接访问它。要确定缓冲区是否由字节数组支持,hasArray()应该使用。

System.out.println(Unpooled.directBuffer().hasArray());(false)

##NIO缓冲区

如果一个ByteBuf可以转换成ByteBuffer共享其内容的NIO (即视图缓冲区),那么可以通过该nioBuffer()方法得到它。要确定缓冲区是否可以转换为NIO缓冲区,请使用nioBufferCount()。

##字符串

各种toString(Charset)方法将ByteBuf 转换成String。请注意,这和Object.toString()不是一种转换方法。

#I / O流

请参考ByteBufInputStream和 ByteBufOutputStream。


		try(ByteBufInputStream bufInputStream = new ByteBufInputStream(Unpooled.copiedBuffer("abcedfg".getBytes()))){
            while(bufInputStream.available()>0){
                System.out.println((char)bufInputStream.read());
            }
        }catch (Exception e){
            e.printStackTrace();
        }


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值