本文是使用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();
}