Netty ByteBuf
2017-07-20 13:27
162 查看
本文是使用Google翻译自: http://netty.io/4.1/api/io/netty/buffer/ByteBuf.html
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缓冲区的抽象视图。
如果剩下可读的内容还不够,IndexOutOfBoundsException将被抛出。默认值通过wrapped或copied新分配ByteBuf的readerIndex是0。
如果没有足够的可写字节剩余,IndexOutOfBoundsException 则被抛出。默认新分配的缓冲区writerIndex是0。通过wrapped或copied分配的缓冲区writerIndex=capacity。
调用discardReadBytes()之前
调用discardReadBytes()之后
readerIndex (0) <= writerIndex (decreased) <= capacity
请注意,调用discardReadBytes()后不能保证可写字节数据内容。在大多数情况下,可写字节数据将不会被移动,甚至可以根据底层缓冲区实现填充完全不同的数据。
BEFORE clear()
AFTER clear()
衍生缓冲器将有一个独立的readerIndex, writerIndex并且标记索引,而这股其他内部数据表示,就像一个NIO缓冲器一样。
如果需要现有缓冲区的全新副本,请调用copy()方法。
类结构
io.netty.bufferClass 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[ 4000 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(); }
相关文章推荐
- netty源码分析之-ByteBuf详解(8)
- 对于 Netty ByteBuf 的零拷贝(Zero Copy)的理解
- Netty入门(四)ByteBuf 字节级别的操作
- Netty - Bytebuf(1)
- 自顶向下深入分析Netty(九)--ByteBuf
- netty(十一)源码分析之ByteBuf 二
- 自顶向下深入分析Netty(九)--ByteBuf源码分析
- Netty - ByteBuf (3)
- Netty 权威指南笔记(五):ByteBuf 源码解读
- Netty - ByteBuf (3)
- Netty的ByteBuf介绍
- netty中ByteBuf部分的分析
- 【Netty源码】ByteBuf源码剖析
- Netty - Bytebuf(1)
- netty源码分析(二十一)Netty数据容器ByteBuf底层数据结构深度剖析与ReferenceCounted初探
- Netty - Bytebuf(1)
- 对于 Netty ByteBuf 的零拷贝(Zero Copy) 的理解
- Netty bytebuf 内存泄漏
- Netty的ByteBuf介绍
- 【Netty】Netty之ByteBuf