官方文档:
Class ByteBuf ------------------ Netty API Reference (4.0.54.Final)
A random and sequential accessible sequence of zero or more bytes (octets). This interface provides an abstract view for one or more primitive byte arrays (byte[]) and NIO buffers.
任意连续可用的序列,包含0或0个以上字节。此接口提供多个原始字节数组和NIO缓冲区的抽象视图。
Creation of a buffer
It is recommended to create a new buffer using the helper methods in Unpooled rather than calling an individual implementation's constructor.
强烈建议用帮助类Unpooled的方法来创建缓冲区,而非直接调用自己的构造函数。
Random Access Indexing
Just like an ordinary primitive byte array, ByteBuf uses zero-based indexing. It means the index of the first byte is always 0 and the index of the last byte is always capacity - 1. For example, to iterate all bytes of a buffer, you can do the following, regardless of its internal implementation:
就像普通的原始字节数组,ByteBuf以0索引开始。这意味着第一个字节的索引总是0,而最后一个字节的索引总是(ByteBuf.capacity-1)。例如,你要遍历一个字符缓冲区,你可以用下面这种方法,不论它的内部实现如何。
ByteBuf buffer = ...;
for (int i = 0; i < buffer.capacity(); i ++) {
byte b = buffer.getByte(i);
System.out.println((char) b);
}
Sequential Access Indexing
ByteBuf provides two pointer variables to support sequential read and write operations - readerIndex for a read operation and writerIndex for a write operation respectively. The following diagram shows how a buffer is segmented into three areas by the two pointers:
ByteBuf 提供两个指针变量来实现连续读和写操作 - readerIndex用于读操作,writerIndex用于写操作。下图显示了缓冲区被两个指针分成三个部分。
Readable bytes (the actual content)
This segment is where the actual data is stored. Any operation whose name starts with read or skip will get or skip the data at the current readerIndex and increase it by the number of read bytes. If the argument of the read operation is also a ByteBuf and no destination index is specified, the specified buffer's writerIndex is increased together.
If there's not enough content left, IndexOutOfBoundsException is raised. The default value of newly allocated, wrapped or copied buffer's readerIndex is 0.
可读字符(实际内容)
这里是实际数据的存储位置。任何以"read"和"skip"开头的操作会以当前的readerIndex上开始读取或忽略指定数据,读取完毕后readerIndex增加。如果读操作的参数也是ByteBuf,且没有指定目标索引,那么缓冲区的writerIndex也会随之增加。
如果没有足够的内容可读,会抛出IndexOutOfBoundsException。新分配的、被封装的或拷贝的缓冲区的readerIndex默认值为0。
// Iterates the readable bytes of a buffer.
ByteBuf buffer = ...;
while (buffer.isReadable()) {
System.out.println(buffer.readByte());
}
Writable bytes
This segment is a undefined space which needs to be filled. Any operation whose name starts with write will write the data at the current writerIndex and increase it by the number of written bytes. If the argument of the write operation is also a ByteBuf, and no source index is specified, the specified buffer's readerIndex is increased together.
If there's not enough writable bytes left, IndexOutOfBoundsException is raised. The default value of newly allocated buffer's writerIndex is 0. The default value of wrapped or copied buffer's writerIndex is the capacity of the buffer.
可写字符
这里是要被填充的被定义空间。任何以"write"开头的操作会以当前writerIndex开始写数据,写完后writerIndex增加。如果写操作的参数也为ByteBuf,且没有指定源索引,那么缓冲区的readerIndex也会随之增加。
如果没有足够的可写字节,会抛出IndexOutOfBoundsException。新分配的缓冲区的writerIndex默认值为0。封装或拷贝的缓冲区的writerIndex默认值为缓冲区的capacity。
// Fills the writable bytes of a buffer with random integers.
ByteBuf buffer = ...;
while (buffer.maxWritableBytes() >= 4) {
buffer.writeInt(random.nextInt());
}
Discardable bytes
This segment contains the bytes which were read already by a read operation. Initially, the size of this segment is 0, but its size increases up to the writerIndex as read operations are executed. The read bytes can be discarded by calling discardReadBytes() to reclaim unused area as depicted by the following diagram:
可废弃字节
这部分包含已读字节。初始化时,这部分的大小为0,但随着读操作的执行,大小会达到writerIndex。已读字节可以通过调用discardReadBytes()废弃,回收可用的空间。下图描述了这个过程
Please note that there is no guarantee about the content of writable bytes after calling discardReadBytes(). The writable bytes will not be moved in most cases and could even be filled with completely different data depending on the underlying buffer implementation.
请注意调用discardReadBytes()后不能保证可读字节的内容。可读字节在大多数情况下不会被移除,还可能会根据不同的底层的缓冲区实现填充不同的数据。
Clearing the buffer indexes
You can set both readerIndex and writerIndex to 0 by calling clear(). It does not clear the buffer content (e.g. filling with 0) but just clears the two pointers. Please also note that the semantic of this operation is different from Buffer.clear().
你可以调用clear()把readerIndex和writerIndex设置为0。它不会清空缓冲区的内容,而仅仅是清除2个指针。请注意这个操作和Buffer.clear()在语义上的不同。
Search operations
For simple single-byte searches, use indexOf(int, int, byte) and bytesBefore(int, int, byte). bytesBefore(byte) is especially useful when you deal with a NUL-terminated string. For complicated searches, use forEachByte(int, int, ByteBufProcessor) with a ByteBufProcessor implementation.
对于简单的单字节搜索,使用indexof(int, int, byte)和bytesBefore(int, int, byte)。bytesBefore(byte)在处理以NUL结尾的字符串时特别有效。对于复杂字符的搜索,使用forEachByte(int, int, ByteBufProcessor)
Mark and reset
There are two marker indexes in every buffer. One is for storing readerIndex and the other is for storing writerIndex. You can always reposition one of the two indexes by calling a reset method. It works in a similar fashion to the mark and reset methods in InputStream except that there's no readlimit.
每个缓冲区有两个标记索引,一个存储readerIndex,另一个存储writerIndex。你总是可以调用reset方法来复位其中一个索引。标记和重置方法在输入流中以相同的方式处理,只不过没有readlimit(读限制)罢了。
Derived buffers
You can create a view of an existing buffer by calling either duplicate(), slice() or slice(int, int). A derived buffer will have an independent readerIndex, writerIndex and marker indexes, while it shares other internal data representation, just like a NIO buffer does.
In case a completely fresh copy of an existing buffer is required, please call copy() method instead.
Also be aware that obtaining derived buffers will NOT call retain() and so the reference count will NOT be increased.
你可以通过调用duplicate()、slice()、或者slice(int, int),创建一个已有缓冲区的视图。衍生的缓冲区有独立的readerIndex,writerIndex,和标记索引,然而它们共享内部数据,就像NIO buffer。
防止全新地复制一个已存在的缓冲区,请用copy()替代。
还有,得到一个衍生的缓冲区不会调用retain(),所以引用计数不会增加。
Conversion to existing JDK types
Byte array
If a ByteBuf is backed by a byte array (i.e. byte[]), you can access it directly via the array() method. To determine if a buffer is backed by a byte array, hasArray() should be used.
NIO Buffers
If a ByteBuf can be converted into an NIO ByteBuffer which shares its content (i.e. view buffer), you can get it via the nioBuffer() method. To determine if a buffer can be converted into an NIO buffer, use nioBufferCount().
Strings
Various toString(Charset) methods convert a ByteBuf into a String. Please note that toString() is not a conversion method.
I/O Streams
Please refer to ByteBufInputStream and ByteBufOutputStream.
字节数组
如果ByteBuf是字节数组,可以用array()方法直接转换。判断ByteBuf是否可以转化为字节数组,可以用hasArray()来确认。
NIO缓冲区
如果一个ByteBuf可以转化为包含一样数据的NIO ByteBuffer,可以使用nioBuffer()来转化。判断ByteBuf是否可以转化为NIO buffer,可以用nioBufferCount()来确认。
字符串
多种 toString(Charset)方法可将ByteBuf转化为String。注意toString()不是转化方法。
I/O流
参考ByteBufInputStream和ByteBufOutputStream