kipedia.org/wiki/Zero-based_numbering">zero-based indexing. It means the index of the first byte is always {@code 0} and the index of the last byte isalways {@link #capacity() capacity - 1}. For example, to iterate all bytes of a buffer, you can do the following, regardless of its internal implementation:
{@link ByteBuf} buffer = ...;for (int i = 0; i < buffer.capacity(); i ++) { byte b = buffer.getByte(i); System.out.println((char) b); }
Sequential Access Indexing
{@link ByteBuf} provides two pointer variables to support sequentialread and write operations - {@link #readerIndex() readerIndex} for a readoperation and {@link #writerIndex() writerIndex} for a write operationrespectively. The following diagram shows how a buffer is segmented into three areas by the two pointers:
+-------------------+------------------+------------------+ | discardable bytes | readable bytes | writable bytes | | | (CONTENT) | | +-------------------+------------------+------------------+ | | | | 0 <= readerIndex <= writerIndex <= capacity
Readable bytes (the actual content)
This segment is where the actual data is stored. Any operation whose name starts with {@code read} or {@code skip} will get or skip the data at thecurrent {@link #readerIndex() readerIndex} and increase it by the number ofread bytes. If the argument of the read operation is also a {@link ByteBuf} and no destination index is specified, the specifiedbuffer's {@link #readerIndex() readerIndex} is increased together.
If there's not enough content left, {@link IndexOutOfBoundsException} israised. The default value of newly allocated, wrapped or copied buffer's {@link #readerIndex() readerIndex} is {@code 0}.
// Iterates the readable bytes of a buffer. {@link ByteBuf} buffer = ...;while (buffer.readable()) { System.out.println(buffer.readByte()); }
Writable bytes
This segment is a undefined space which needs to be filled. Any operation whose name ends with {@code write} will write the data at the current{@link #writerIndex() writerIndex} and increase it by the number of writtenbytes. If the argument of the write operation is also a {@link ByteBuf}, and no source index is specified, the specified buffer's {@link #readerIndex() readerIndex} is increased together.
If there's not enough writable bytes left, {@link IndexOutOfBoundsException}is raised. The default value of newly allocated buffer's {@link #writerIndex() writerIndex} is {@code 0}. The default value of wrapped or copied buffer's {@link #writerIndex() writerIndex} is the{@link #capacity() capacity} of the buffer.
// Fills the writable bytes of a buffer with random integers. {@link ByteBuf} buffer = ...;while (buffer.writableBytes() >= 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 {@code 0}, but its size increases up to the {@link #writerIndex() writerIndex} as read operations are executed.The read bytes can be discarded by calling {@link #discardReadBytes()} toreclaim unused area as depicted by the following diagram:
BEFORE discardReadBytes() +-------------------+------------------+------------------+ | discardable bytes | readable bytes | writable bytes | +-------------------+------------------+------------------+ | | | | 0 <= readerIndex <= writerIndex <= capacity AFTER discardReadBytes() +------------------+--------------------------------------+ | readable bytes | writable bytes (got more space) | +------------------+--------------------------------------+ | | | readerIndex (0) <= writerIndex (decreased) <= capacity
Please note that there is no guarantee about the content of writable bytes after calling {@link #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.
Clearing the buffer indexes
You can set both {@link #readerIndex() readerIndex} and{@link #writerIndex() writerIndex} to {@code 0} by calling {@link #clear()}. It does not clear the buffer content (e.g. filling with {@code 0}) but just clears the two pointers. Please also note that the semantic of this operation is different from {@link ByteBuffer#clear()}.
BEFORE clear() +-------------------+------------------+------------------+ | discardable bytes | readable bytes | writable bytes | +-------------------+------------------+------------------+ | | | | 0 <= readerIndex <= writerIndex <= capacity AFTER clear() +---------------------------------------------------------+ | writable bytes (got more space) | +---------------------------------------------------------+ | | 0 = readerIndex = writerIndex <= capacity
Search operations
Various {@link #indexOf(int,int,byte)} methods help you locate an index ofa value which meets a certain criteria. Complicated dynamic sequential search can be done with {@link ByteBufIndexFinder} as well as simplestatic single byte search.
If you are decoding variable length data such as NUL-terminated string, you will find {@link #bytesBefore(byte)} also useful.
Mark and reset
There are two marker indexes in every buffer. One is for storing {@link #readerIndex() readerIndex} and the other is for storing{@link #writerIndex() 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 {@link InputStream} except that there's no{@code readlimit}.
Derived buffers
You can create a view of an existing buffer by calling either {@link #duplicate()}, {@link #slice()} or {@link #slice(int,int)}. A derived buffer will have an independent {@link #readerIndex() readerIndex}, {@link #writerIndex() writerIndex} and marker indexes, while it sharesother internal data representation, just like a NIO buffer does.
In case a completely fresh copy of an existing buffer is required, please call {@link #copy()} method instead.
Conversion to existing JDK types
Byte array
If a {@link ByteBuf} is backed by a byte array (i.e. {@code byte[]}), you can access it directly via the {@link #array()} method. To determineif a buffer is backed by a byte array, {@link #hasArray()} should be used.
NIO Buffers
If a {@link ByteBuf} can be converted into an NIO {@link ByteBuffer} which shares itscontent (i.e. view buffer), you can get it via the {@link #nioBuffer()} method. To determineif a buffer can be converted into an NIO buffer, use {@link #nioBuffer()}.
Strings
Various {@link #toString(Charset)} methods convert a {@link ByteBuf}into a {@link String}. Please note that {@link #toString()} is not aconversion method.
I/O Streams
Please refer to {@link ByteBufInputStream} and{@link ByteBufOutputStream}.