Netty Associated -- ByteBuf

ByteBuf

ByteBuf是Netty的Server与Client之间通讯的数据传输载体.他提供了一个byte数组(byte[])的抽象视图数组

buffer建立

咱们推荐经过一个Unpooled的帮助方法来建立新的buffer而不是经过调用独立的构造器来建立dom

随机访问索引

就像普通的原声字节数组同样, ByteBuf使用零基坐标(zero-based indexing). 这表示第一个字节的坐标老是0, 最后一个字节的坐标老是capacity - 1.例如, 要遍历buffer的全部字节,你能够按下面这样作:spa

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

连续访问索引

ByteBuf提供了两个指针变量来支持顺序读写操做 - readerIndex用来支持读操做, writerIndex用来支持写操做.下面的表格显示了一个buffer是如何经过两个指针分段为三部分的3d

可读字节(真实内容)

这个段是真实数据储存的地方.任何名字以start或skip开始的操做都会增长当前readerIndex他读过的字节数.若是读操做的参数也是一个ByteBuf, 而且没有指定目的地坐标, 那么指定ByteBuf的writerIndex也会一块儿增长指针

若是buf没有足够的内容可供读取,会抛出IndexOutOfBoundsException. 最新分配的buffer, buffer的包装类和副本的readerIndex默认值都是0code

   // Iterates the readable bytes of a buffer.
   ByteBuf buffer = ...;
   while (buffer.readable()) {
       System.out.println(buffer.readByte());
   }

可写字节

这个段是一个等待被填满的未定义空间.任何名字已write结尾的操做都会在当前writerIndex上写入数据,而且将writerIndex的值增长写入的数据数.若是写入操做的参数也是一个ByteBuf, 而且没有元坐标被指定, 那么指定的buffer的readerIndex也会一块儿增长blog

若是没有组合够的空间剩余来写,会抛出IndexOutOfBoundsException. 最新分配的buffer的writerIndex的默认值是0, 包装类和buffer副本的writerIndex是buffer的容量索引

   // Fills the writable bytes of a buffer with random integers.
   ByteBuf buffer = ...;
   while (buffer.maxWritableBytes() >= 4) {
       buffer.writeInt(random.nextInt());
   }

 丢弃字节

这个段包含已经被读操做读过的字节.初始化的时候, 这个段的大小为0,这个段的大小会随着读操做一直增长到writerIndex.读字节能够经过discardReadBytes()回收未被使用的区域将其变为丢弃字节, 以下图所示ip

 

调用discardReadBytes()前:内存

 

使用discardReadBytes()后:

请注意并不能保证在调用discardReadBytes()后并不能保证可写字节的内容.可写字节在大部分状况下不会移动, 而且可能被彻底不一样的数据填满, 这取决于底层的buffer实现.

 

清除buffer索引

你能够经过调用clear()将readerIndex和writerIndex都设为0.这不会清除buffer内容(例如用0填充), 他仅仅是清除了两个指针.请注意这个操做的语义和ByteBuffer.clear()是不同的

clear()前

clear()后

 

搜索操做

使用indexOf(int, int, byte)和bytesBefore(int, int, byte)能够进行最简单的单字节搜索.bytesBefore(byte)在你处理一个NUL-terminated字符串的时候特别有用.更复杂的搜索, 请使用forEachByte(int, int, ByteBufProcessor)和一个ByteBufProcessor的实现

 

标记和重置

每一个buffer都有两个标记索引.一个用来保存readerIndex,另外一个用来保存writerIndex.你能够经过调用reset()放来来重置他们中的一个.他的工做方式和InputStream中的mark和reset方法很像, 只是没有readlimit

 

派生buffer

你能够经过调用duplicate(), slice()或者slice(int, int)来建立一个已存在的buffer的视图.一个派生的buffer会有单独的readerIndex,writerIndex和标记坐标, 可是他共享其余数据.就像一个NIO的buffer同样.

加入你须要一个全新的buffer的copy,请调用copy()方法

 

转化为已存在的JDK类型

Byte array

假如一个ByteBuf是有一个byte数组做为支持的, 你能够直接经过array()方法访问它. 判断一个buffer是不是被byte array做为支持,调用hasArray()

只有堆内内存的ByteBuf是有array支持的, 若是是堆外内存的ByteBuf, 是不能经过array()获取到数据的, 而CompositeByteBuf可能由堆内的ByteBuf和堆外的DirectByteBuf组成, 他也不能直接经过array()获取数据

 

NIO Buffers

若是一个ByteBuf能够被转换为NIO ByteBuffer, 他共享他的内容,你能够经过nioBuffer()获取它.判断一个buffer可否被转化为NIO buffer, 使用nioBufferCount().

 

Strings

各类各样的toString(Charset)方法将一个ByteBuf转化为一个String.请注意toString()并非一个转换方法.

 

I/O Streams

请看ByteBufInputStream和ByteBufOutputStream

相关文章
相关标签/搜索