- 浏览: 999820 次
-
文章分类
- 全部博客 (428)
- Hadoop (2)
- HBase (1)
- ELK (1)
- ActiveMQ (13)
- Kafka (5)
- Redis (14)
- Dubbo (1)
- Memcached (5)
- Netty (56)
- Mina (34)
- NIO (51)
- JUC (53)
- Spring (13)
- Mybatis (17)
- MySQL (21)
- JDBC (12)
- C3P0 (5)
- Tomcat (13)
- SLF4J-log4j (9)
- P6Spy (4)
- Quartz (12)
- Zabbix (7)
- JAVA (9)
- Linux (15)
- HTML (9)
- Lucene (0)
- JS (2)
- WebService (1)
- Maven (4)
- Oracle&MSSQL (14)
- iText (11)
- Development Tools (8)
- UTILS (4)
- LIFE (8)
最新评论
-
Donald_Draper:
Donald_Draper 写道刘落落cici 写道能给我发一 ...
DatagramChannelImpl 解析三(多播) -
Donald_Draper:
刘落落cici 写道能给我发一份这个类的源码吗Datagram ...
DatagramChannelImpl 解析三(多播) -
lyfyouyun:
请问楼主,执行消息发送的时候,报错:Transport sch ...
ActiveMQ连接工厂、连接详解 -
ezlhq:
关于 PollArrayWrapper 状态含义猜测:参考 S ...
WindowsSelectorImpl解析一(FdMap,PollArrayWrapper) -
flyfeifei66:
打算使用xmemcache作为memcache的客户端,由于x ...
Memcached分布式客户端(Xmemcached)
netty 通道接口定义:http://donald-draper.iteye.com/blog/2392740
netty 抽象通道初始化:http://donald-draper.iteye.com/blog/2392801
netty 抽象Unsafe定义:http://donald-draper.iteye.com/blog/2393053
netty 通道Outbound缓冲区:http://donald-draper.iteye.com/blog/2393098
netty 抽象通道后续:http://donald-draper.iteye.com/blog/2393166
netty 抽象nio通道:http://donald-draper.iteye.com/blog/2393269
netty 抽象nio字节通道:http://donald-draper.iteye.com/blog/2393323
netty 抽象nio消息通道:http://donald-draper.iteye.com/blog/2393364
netty NioServerSocketChannel解析:http://donald-draper.iteye.com/blog/2393443
netty 通道配置接口定义:http://donald-draper.iteye.com/blog/2393484
netty 默认通道配置初始化:http://donald-draper.iteye.com/blog/2393504
netty 默认通道配置后续:http://donald-draper.iteye.com/blog/2393510
引言
前面两篇文章我们看了通道配置,先来简单回顾一下:
默认通道配置内部主要是配置消息大小估算器,字节buf分配器,接收字节buf分配器等属性。默认ServerSocket通道配置,与ServerSocket相关的配置委托给ServerSocket的相关方法,其他委托给父类默认通道配置。默认Socket通道配置,与Socket相关的配置委托给Socket的相关方法,其他委托给父类默认通道配置。
在上面的两篇文章中,我们有说过字节buf分配器,字节buf分配器可以创建direct和heap类型的ByteBuf,接下来的文章先看一下
字节buf接口的定义,再看字节buf分配器非配的direct和heap类型的字节buf实现。先从字节buf接口定义:
再看字节buf接口定义前,来看一下引用计数器接口的定义:
从上面可以看出,对象引用计数器ReferenceCounted,主要记录对象的引用数量,当引用数量为0时,表示可以回收对象,在调试模式下,如果发现对象出现内存泄漏,可以用touch方法记录操作的相关信息,通过ResourceLeakDetector获取操作的相关信息,以便分析内存泄漏的原因。
再来看字节buf的接口定义:
总结:
对象引用计数器ReferenceCounted,主要记录对象的引用数量,当引用数量为0时,表示可以回收对象,在调试模式下,如果发现对象出现内存泄漏,可以用touch方法记录操作的相关信息,通过ResourceLeakDetector获取操作的相关信息,以便分析内存泄漏的原因。
字节缓存ByteBuf继承了对象引用计数器ReferenceCounted,拥有一个最大容量限制,如果用户尝试用 #capacity(int)和 #ensureWritable(int)方法,增加buf容量超过最大容量,将会抛出非法参数异常;字节buf有两个索引,一个为读索引readerIndex,一个为写索引writerIndex,读索引不能大于写索引,写索引不能小于读索引,buf可读字节数为writerIndex - readerIndex,buf可写字节数为capacity - writerIndex,buf可写的最大字节数为maxCapacity - writerIndex;
可以使用markReader/WriterIndex标记当前buf读写索引位置,resetReader/WriterIndex方法可以重回先前标记的索引位置;
当内存空间负载过度时,我们可以使用discardReadBytes丢弃一些数据,以节省空间;
我们可以使用ensureWritable检测当buf是否有足够的空间写数据;
提供了getBytes方法,可以将buf中的数据转移到目的ByteBuf,Byte数组,Nio字节buf ByteBuffer,OutputStream,聚集字节通道
GatheringByteChannel和文件通道FileChannel中,这些方法不会修改当前buf读写索引,具体是否修改目的对象索引或位置,见java doc 描述。
提供了setBytes方法,可以将源ByteBuf,Byte数组,Nio字节buf ByteBuffer,InputputStream,分散字节通道ScatteringByteChannel和文件通道FileChannel中的数据转移到当前buf中,这些方法不会修改当前buf的读写索引,至于源对象索引或位置,见java doc 描述。
提供了readBytes方法,可以将buf中的数据转移到目的ByteBuf,Byte数组,Nio字节buf ByteBuffer,OutputStream,聚集字节通道GatheringByteChannel和文件通道FileChannel中,这些方法具体会会修改当前buf读索引,至于会不会修改源对象索引或位置,见java doc 描述。
提供了writeBytes方法,可以将源ByteBuf,Byte数组,Nio字节buf ByteBuffer,
InputputStream,分散字节通道ScatteringByteChannel和文件通道FileChannel中的数据写到当前buf中,这些方法会修改当前buf的写索引,至于会不会修改源对象索引或位置,见java
doc 描述。
set*原始类型方法不会修改读写索引;
get*原始类型方法不会修改读写索引;
write*原始类型方法会修改写索引;
read*原始类型方法,会修改读索引;
字节buf中的set/get*方法不会修改当前buf的读写索引,而write*修改写索引,read*会修改读索引;
提供了copy,slice和retainSlice,duplicate和retainedDuplicate方法,用于拷贝,切割,复制当前buf数据,retained*方法会增加buf的引用计数器;
提供nioBuffer和nioBuffers方法,用于包装当前buf可读数据为java nio ByteBuffer和ByteBuffer数组。
附:
下面是字节buf的get*原始类型方法的定义,简单看一下:
下面的方法不会修改读写索引
下面一些set*原始类型方法从索引index开始,设置原始类型,不会修改读写索引
以下一些read*原始类型方法,会修改读索引
下面是一些write*原始类型的方法,会增加写索引
下面是一些字节搜索定位方法:
//ByteProcessor
netty 抽象通道初始化:http://donald-draper.iteye.com/blog/2392801
netty 抽象Unsafe定义:http://donald-draper.iteye.com/blog/2393053
netty 通道Outbound缓冲区:http://donald-draper.iteye.com/blog/2393098
netty 抽象通道后续:http://donald-draper.iteye.com/blog/2393166
netty 抽象nio通道:http://donald-draper.iteye.com/blog/2393269
netty 抽象nio字节通道:http://donald-draper.iteye.com/blog/2393323
netty 抽象nio消息通道:http://donald-draper.iteye.com/blog/2393364
netty NioServerSocketChannel解析:http://donald-draper.iteye.com/blog/2393443
netty 通道配置接口定义:http://donald-draper.iteye.com/blog/2393484
netty 默认通道配置初始化:http://donald-draper.iteye.com/blog/2393504
netty 默认通道配置后续:http://donald-draper.iteye.com/blog/2393510
引言
前面两篇文章我们看了通道配置,先来简单回顾一下:
默认通道配置内部主要是配置消息大小估算器,字节buf分配器,接收字节buf分配器等属性。默认ServerSocket通道配置,与ServerSocket相关的配置委托给ServerSocket的相关方法,其他委托给父类默认通道配置。默认Socket通道配置,与Socket相关的配置委托给Socket的相关方法,其他委托给父类默认通道配置。
在上面的两篇文章中,我们有说过字节buf分配器,字节buf分配器可以创建direct和heap类型的ByteBuf,接下来的文章先看一下
字节buf接口的定义,再看字节buf分配器非配的direct和heap类型的字节buf实现。先从字节buf接口定义:
public abstract class ByteBuf implements ReferenceCounted, Comparable<ByteBuf> {
再看字节buf接口定义前,来看一下引用计数器接口的定义:
package io.netty.util; /** * A reference-counted object that requires explicit deallocation. * * When a new {@link ReferenceCounted} is instantiated, it starts with the reference count of {@code 1}. * {@link #retain()} increases the reference count, and {@link #release()} decreases the reference count. * If the reference count is decreased to {@code 0}, the object will be deallocated explicitly, and accessing * the deallocated object will usually result in an access violation. * * * If an object that implements {@link ReferenceCounted} is a container of other objects that implement * {@link ReferenceCounted}, the contained objects will also be released via {@link #release()} when the container's * reference count becomes 0. * */ public interface ReferenceCounted { /** * Returns the reference count of this object. If {@code 0}, it means this object has been deallocated. 返回对象的引用计数器,为0,表示对象可以被回收 */ int refCnt(); /** * Increases the reference count by {@code 1}. 对象引用计数器自增1 */ ReferenceCounted retain(); /** * Increases the reference count by the specified {@code increment}. 增加引用计数器,增量为increment */ ReferenceCounted retain(int increment); /** * Records the current access location of this object for debugging purposes. * If this object is determined to be leaked, the information recorded by this operation will be provided to you * via {@link ResourceLeakDetector}. This method is a shortcut to {@link #touch(Object) touch(null)}. 调试时,记录当前对象访问的位置。如果对象确定内存泄漏,可以通过ResourceLeakDetector获取操作的相关信息。 此方法为 #touch(Object) touch(null)的快捷方式 */ ReferenceCounted touch(); /** * Records the current access location of this object with an additional arbitrary information for debugging * purposes. If this object is determined to be leaked, the information recorded by this operation will be * provided to you via {@link ResourceLeakDetector}. 调试时,记录当前对象访问的位置。如果对象确定内存泄漏,可以通过ResourceLeakDetector获取操作的相关信息。 */ ReferenceCounted touch(Object hint); /** * Decreases the reference count by {@code 1} and deallocates this object if the reference count reaches at * {@code 0}. *自减对象引用计数器,如果引用数为0,则回收对象。当且仅当对象引用计数器为0,回收对象,返回true * @return {@code true} if and only if the reference count became {@code 0} and this object has been deallocated */ boolean release(); /** * Decreases the reference count by the specified {@code decrement} and deallocates this object if the reference * count reaches at {@code 0}. *减对象引用计数器,减量为decrement,如果引用数为0,则回收对象。当且仅当对象引用计数器为0,回收对象,返回true * @return {@code true} if and only if the reference count became {@code 0} and this object has been deallocated */ boolean release(int decrement); }
从上面可以看出,对象引用计数器ReferenceCounted,主要记录对象的引用数量,当引用数量为0时,表示可以回收对象,在调试模式下,如果发现对象出现内存泄漏,可以用touch方法记录操作的相关信息,通过ResourceLeakDetector获取操作的相关信息,以便分析内存泄漏的原因。
再来看字节buf的接口定义:
package io.netty.buffer; import io.netty.util.ByteProcessor; import io.netty.util.ReferenceCounted; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.channels.FileChannel; import java.nio.channels.GatheringByteChannel; import java.nio.channels.ScatteringByteChannel; import java.nio.charset.Charset; import java.nio.charset.UnsupportedCharsetException; /** * 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 ({@code byte[]}) and {@linkplain ByteBuffer NIO buffers}. *字节缓冲ByteBuf是一个可随机方法字节序列,字节数可以为0或更多。 这个方法提供了一个或更多原始字节数组和java nio ByteBuffer的抽象视图。 * <h3>Creation of a buffer</h3> *创建buf * It is recommended to create a new buffer using the helper methods in * {@link Unpooled} rather than calling an individual implementation's * constructor. *强烈建议使用Unpooled的辅助方法创建一个字节buf,而不是调用buf具体实现的构造方法。 * <h3>Random Access Indexing</h3> *随机访问索引 * Just like an ordinary primitive byte array, {@link ByteBuf} uses * [url=http://en.wikipedia.org/wiki/Zero-based_numbering]zero-based indexing[/url]. * It means the index of the first byte is always {@code 0} and the index of the last byte is * always {@link #capacity() capacity - 1}. For example, to iterate all bytes of a buffer, you * can do the following, regardless of its internal implementation: *如一般的字节数组一样,字节buf索引也是从0开始。意味着第一个字节的索引总是为0,最后一个字节的 索引总是为#capacity() capacity - 1。比如,遍历buf中的所有字节,忽略具体实现的情况下, 可以按如下code * <pre> * {@link ByteBuf} buffer = ...; * for (int i = 0; i < buffer.capacity(); i ++) { * byte b = buffer.getByte(i); * System.out.println((char) b); * } * </pre> * * <h3>Sequential Access Indexing</h3> *顺序访问索引 * {@link ByteBuf} provides two pointer variables to support sequential * read and write operations - {@link #readerIndex() readerIndex} for a read * operation and {@link #writerIndex() writerIndex} for a write operation * respectively. The following diagram shows how a buffer is segmented into * three areas by the two pointers: *字节buf提供了两个索引支持顺序读写操作,#readerIndex返回读操作使用的读索引readerIndex, #writerIndex返回写操作使用的写索引writerIndex。下图展示读写索引如何将buf分为三段。 * <pre> * +-------------------+------------------+------------------+ * | discardable bytes | readable bytes | writable bytes | * | | (CONTENT) | | * +-------------------+------------------+------------------+ * | | | | * 0 <= readerIndex <= writerIndex <= capacity * </pre> * * <h4>Readable bytes (the actual content)</h4> *可读字节(实际内容) * 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 the * current {@link #readerIndex() readerIndex} and increase it by the number of * read bytes. If the argument of the read operation is also a * {@link ByteBuf} and no destination index is specified, the specified * buffer's {@link #writerIndex() writerIndex} is increased together. 这段内容为实际存储的数据。任何以read和skip开头的操作方法,将会从当前的读索引开始, 并增加读索引,增量为读取的字节数。如果读操作的参数为字节buf,并且没有目的索引, 那么目的buf写索引也会增加。 * <p> * If there's not enough content left, {@link IndexOutOfBoundsException} is * raised. The default value of newly allocated, wrapped or copied buffer's * {@link #readerIndex() readerIndex} is {@code 0}. *如果没有足够的内容,将会抛出IndexOutOfBoundsException异常。默认新分配, copy,包装的字节buf的读索引为0。 * <pre> * // Iterates the readable bytes of a buffer. * {@link ByteBuf} buffer = ...; * while (buffer.isReadable()) { * System.out.println(buffer.readByte()); * } * </pre> * * <h4>Writable bytes</h4> *可写字节 * This segment is a undefined space which needs to be filled. Any operation * whose name starts with {@code write} will write the data at the current * {@link #writerIndex() writerIndex} and increase it by the number of written * bytes. 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. 此段是需要填充的无定义空间。任何以write开头的操作方法,将会从当前的写索引开始写字节数据, 并增加写索引,增量为写的字节数。如果写操作的参数为字节buf,并且没有源索引,则源buf的读索引 将会增加 * <p> * 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. * 如果没有足够的可写字节,将抛出IndexOutOfBoundsException异常。默认新分配的buf的写索引为0。 copy,包装的字节buf的写索引为#capacity() capacity * <pre> * // Fills the writable bytes of a buffer with random integers. 写随机整数到buf * {@link ByteBuf} buffer = ...; * while (buffer.maxWritableBytes() >= 4) { * buffer.writeInt(random.nextInt()); * } * </pre> * * <h4>Discardable bytes</h4> *可丢弃的字节数 * 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()} to * reclaim unused area as depicted by the following diagram: *这段包含了读操作已经读取的字节。初始情况下,这段长度为0,但是这段的长度随着 读操作的执行,增加至写索引。这段数据可以调用#discardReadBytes方法丢弃, 并重新收回没用的区域,具体描述如下图: * <pre> * 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 * </pre> * * 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. *需要注意的是,在丢弃已经读取的字节时,并不能保证可写字节的内容。可写字节在大多数情况下不会 移动,甚至可能填充不同的数据,这个依赖于具体的buf实现。 * <h4>Clearing the buffer indexes</h4> *清除buf索引 * 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()}. *我们可以调用#clear方法,设置读写索引为0。clear方法不会清除buf中的数据,仅仅调整 读写索引。需要注意的是此方法不同于java nio ByteBuffer#clear方法。 * <pre> * BEFORE clear() * * +-------------------+------------------+------------------+ * | discardable bytes | readable bytes | writable bytes | * +-------------------+------------------+------------------+ * | | | | * 0 <= readerIndex <= writerIndex <= capacity * * * AFTER clear() * * +---------------------------------------------------------+ * | writable bytes (got more space) | * +---------------------------------------------------------+ * | | * 0 = readerIndex = writerIndex <= capacity * </pre> * * <h3>Search operations</h3> *搜索操作 * For simple single-byte searches, use {@link #indexOf(int, int, byte)} and {@link #bytesBefore(int, int, byte)}. * {@link #bytesBefore(byte)} is especially useful when you deal with a {@code NUL}-terminated string. * For complicated searches, use {@link #forEachByte(int, int, ByteProcessor)} with a {@link ByteProcessor} * implementation. 对于简单的单个字节搜索,可是使用#indexOf和#bytesBefore方法。当需要处理一个空字节NUL(0x00)时, #bytesBefore方法特别有用。 比如一些复杂的搜索,可以使用字节处理器ByteProcessor版的#forEachByte方法。 * * <h3>Mark and reset</h3> *标记和重置 * 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}. *在每个buf中有两个标记索引,一个是存储读索引的,一个是存储写索引的。你可以 调用reset方法,重置读、写索引到标记的位置。除了没有readlimit之外,与输入流中标记和重置方法 相似。 * <h3>Derived buffers</h3> *衍生buf * You can create a view of an existing buffer by calling one of the following methods: 你可通过如下方法,创建buf的视图: * [list] * [*]{@link #duplicate()} * [*]{@link #slice()} * [*]{@link #slice(int, int)} * [*]{@link #readSlice(int)} * [*]{@link #retainedDuplicate()} * [*]{@link #retainedSlice()} * [*]{@link #retainedSlice(int, int)} * [*]{@link #readRetainedSlice(int)} * [/list] * A derived buffer will have an independent {@link #readerIndex() readerIndex}, * {@link #writerIndex() writerIndex} and marker indexes, while it shares * other internal data representation, just like a NIO buffer does. 衍生buf,拥有自己独立的读写索引的标记索引,共享其他内部数据,就像java nio ByteBuffer * <p> * In case a completely fresh copy of an existing buffer is required, please * call {@link #copy()} method instead. *假如需要当前buf的完全拷贝,可以使用copy方法。 * <h4>Non-retained and retained derived buffers</h4> *非retained和retained衍生buf * Note that the {@link #duplicate()}, {@link #slice()}, {@link #slice(int, int)} and {@link #readSlice(int)} does NOT * call {@link #retain()} on the returned derived buffer, and thus its reference count will NOT be increased. If you * need to create a derived buffer with increased reference count, consider using {@link #retainedDuplicate()}, * {@link #retainedSlice()}, {@link #retainedSlice(int, int)} and {@link #readRetainedSlice(int)} which may return * a buffer implementation that produces less garbage. *注意#duplicate,#slice,#slice,#readSlice方法不会在衍生buf中调用#retain方法,这样buf的引用计数器将不会增加。 如果需要创建衍生buf,需要增加引用计数器,可以考虑上述方法的#retained*版本方法,这样可能会产生一点内存垃圾。 * <h3>Conversion to existing JDK types</h3> *转换ByteBuf为JDK 类型 * <h4>Byte array</h4> *字节数组 * 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 determine * if a buffer is backed by a byte array, {@link #hasArray()} should be used. *如果字节是一个字节数组,你可以直接使用#array访问。判断一个方法是否为字节数组,可以 使用#hasArray方法 * <h4>NIO Buffers</h4> *nio ByteBuffer * If a {@link ByteBuf} can be converted into an NIO {@link ByteBuffer} which shares its * content (i.e. view buffer), you can get it via the {@link #nioBuffer()} method. To determine * if a buffer can be converted into an NIO buffer, use {@link #nioBufferCount()}. *如果字节buf可以转换为java nio ByteBuffer,你可以调用#nioBuffer方法共享buf内容。 你可以使用#nioBufferCount来判断字节buf可不可以转换为java nio ByteBuffer * <h4>Strings</h4> *字符串 * Various {@link #toString(Charset)} methods convert a {@link ByteBuf} * into a {@link String}. Please note that {@link #toString()} is not a * conversion method. *#toString(Charset)方法转换字节buf为字符串,注意#toString不是一个转换方法 * <h4>I/O Streams</h4> *IO流 * Please refer to {@link ByteBufInputStream} and * {@link ByteBufOutputStream}. 参考ByteBufInputStream和ByteBufOutputStream */ @SuppressWarnings("ClassMayBeInterface") public abstract class ByteBuf implements ReferenceCounted, Comparable<ByteBuf> { /** * Returns the number of bytes (octets) this buffer can contain. 获取buf容量 */ public abstract int capacity(); /** * Adjusts the capacity of this buffer. If the {@code newCapacity} is less than the current * capacity, the content of this buffer is truncated. If the {@code newCapacity} is greater * than the current capacity, the buffer is appended with unspecified data whose length is * {@code (newCapacity - currentCapacity)}. 调整buf的容量,如果容量小于原始buf容量,则truncated buf的内容,如果新增量大于原始容量, 则buffer将会添加不确定的数,其长度为newCapacity - currentCapacity */ public abstract ByteBuf capacity(int newCapacity); /** * Returns the maximum allowed capacity of this buffer. If a user attempts to increase the * capacity of this buffer beyond the maximum capacity using {@link #capacity(int)} or * {@link #ensureWritable(int)}, those methods will raise an * {@link IllegalArgumentException}. 返回buf的最大允许容量。如果用户尝试用 #capacity(int)和 #ensureWritable(int)方法, 增加buf容量超过最大容量,将会抛出非法参数异常 */ public abstract int maxCapacity(); /** * Returns the {@link ByteBufAllocator} which created this buffer. 返回创建buf的字节buf分配器 */ public abstract ByteBufAllocator alloc(); /** * Returns the [url=http://en.wikipedia.org/wiki/Endianness]endianness[/url] * of this buffer. *已丢弃 * @deprecated use the Little Endian accessors, e.g. {@code getShortLE}, {@code getIntLE} * instead of creating a buffer with swapped {@code endianness}. */ @Deprecated public abstract ByteOrder order(); /** * Returns a buffer with the specified {@code endianness} which shares the whole region, * indexes, and marks of this buffer. Modifying the content, the indexes, or the marks of the * returned buffer or this buffer affects each other's content, indexes, and marks. If the * specified {@code endianness} is identical to this buffer's byte order, this method can * return {@code this}. This method does not modify {@code readerIndex} or {@code writerIndex} * of this buffer. *已丢弃 * @deprecated use the Little Endian accessors, e.g. {@code getShortLE}, {@code getIntLE} * instead of creating a buffer with swapped {@code endianness}. */ @Deprecated public abstract ByteBuf order(ByteOrder endianness); /** * Return the underlying buffer instance if this buffer is a wrapper of another buffer. *如果buf为另一个buf包装类,返回底层buf实例,即返回未包装的buf * @return {@code null} if this buffer is not a wrapper */ public abstract ByteBuf unwrap(); /** * Returns {@code true} if and only if this buffer is backed by an * NIO direct buffer. 判断buf是否是direct类型 */ public abstract boolean isDirect(); /** * Returns {@code true} if and only if this buffer is read-only. 判断buf是否可读 */ public abstract boolean isReadOnly(); /** * Returns a read-only version of this buffer. 返回buf的只读版本 */ public abstract ByteBuf asReadOnly(); /** * Returns the {@code readerIndex} of this buffer. 获取buf的读索引 */ public abstract int readerIndex(); /** * Sets the {@code readerIndex} of this buffer. *设置buf的读索引 * @throws IndexOutOfBoundsException * if the specified {@code readerIndex} is * less than {@code 0} or * greater than {@code this.writerIndex} */ public abstract ByteBuf readerIndex(int readerIndex); /** * Returns the {@code writerIndex} of this buffer. 获取buf的写索引 */ public abstract int writerIndex(); /** * Sets the {@code writerIndex} of this buffer. *设置buf的写索引 * @throws IndexOutOfBoundsException * if the specified {@code writerIndex} is * less than {@code this.readerIndex} or * greater than {@code this.capacity} */ public abstract ByteBuf writerIndex(int writerIndex); /** * Sets the {@code readerIndex} and {@code writerIndex} of this buffer * in one shot. This method is useful when you have to worry about the * invocation order of {@link #readerIndex(int)} and {@link #writerIndex(int)} * methods. For example, the following code will fail: *设置buf读写索引的快捷方式。当你不得不关心读索引设置和写索引设置的顺序时,这个方法,非常有用。 以下代码将会失败: * <pre> * // Create a buffer whose readerIndex, writerIndex and capacity are * // 0, 0 and 8 respectively. * {@link ByteBuf} buf = {@link Unpooled}.buffer(8); * * // IndexOutOfBoundsException is thrown because the specified * // readerIndex (2) cannot be greater than the current writerIndex (0). 读索引不能大于当前的写索引 * buf.readerIndex(2); * buf.writerIndex(4); * </pre> * * The following code will also fail: *同样下面的代码会失败 * <pre> * // Create a buffer whose readerIndex, writerIndex and capacity are * // 0, 8 and 8 respectively. * {@link ByteBuf} buf = {@link Unpooled}.wrappedBuffer(new byte[8]); * * // readerIndex becomes 8. * buf.readLong(); * * // IndexOutOfBoundsException is thrown because the specified * // writerIndex (4) cannot be less than the current readerIndex (8). 写索引小于读索引 * buf.writerIndex(4); * buf.readerIndex(2); * </pre> * * By contrast, this method guarantees that it never * throws an {@link IndexOutOfBoundsException} as long as the specified * indexes meet basic constraints, regardless what the current index * values of the buffer are: *相比之下,setIndex方法可以保证只要索引满足基本的约束,无论当前buf索引的值是什么, 索引越界异常不会抛出. * <pre> * // No matter what the current state of the buffer is, the following * // call always succeeds as long as the capacity of the buffer is not * // less than 4. 只要buf的容量大于4,就不会抛出异常 * buf.setIndex(2, 4); * </pre> * * @throws IndexOutOfBoundsException * if the specified {@code readerIndex} is less than 0, * if the specified {@code writerIndex} is less than the specified * {@code readerIndex} or if the specified {@code writerIndex} is * greater than {@code this.capacity} */ public abstract ByteBuf setIndex(int readerIndex, int writerIndex); /** * Returns the number of readable bytes which is equal to 获取buf可读字节数为writerIndex - readerIndex * {@code (this.writerIndex - this.readerIndex)}. */ public abstract int readableBytes(); /** * Returns the number of writable bytes which is equal to 获取buf可写字节数为capacity - writerIndex * {@code (this.capacity - this.writerIndex)}. */ public abstract int writableBytes(); /** * Returns the maximum possible number of writable bytes, which is equal to * {@code (this.maxCapacity - this.writerIndex)}. 当前buf可写的最大字节数为maxCapacity - writerIndex */ public abstract int maxWritableBytes(); /** * Returns {@code true} * if and only if {@code (this.writerIndex - this.readerIndex)} is greater * than {@code 0}. 获取buf是否可读,如果当前可读字节数大于0,表示可读,返回true */ public abstract boolean isReadable(); /** * Returns {@code true} if and only if this buffer contains equal to or more than the specified number of elements. buf的可读字节数据是否大于size */ public abstract boolean isReadable(int size); /** * Returns {@code true} * if and only if {@code (this.capacity - this.writerIndex)} is greater * than {@code 0}. buf是否可写,即this.capacity - this.writerIndex是否大于0 */ public abstract boolean isWritable(); /** * Returns {@code true} if and only if this buffer has enough room to allow writing the specified number of * elements. 判断当前buf是否可容下size字节 */ public abstract boolean isWritable(int size); /** * Sets the {@code readerIndex} and {@code writerIndex} of this buffer to * {@code 0}. 重置buf的读写索引为0,等同于setIndex(0, 0) * This method is identical to {@link #setIndex(int, int) setIndex(0, 0)}. * <p> * Please note that the behavior of this method is different * from that of NIO buffer, which sets the {@code limit} to * the {@code capacity} of the buffer. 主要此方法,不同于Java nio buffer,设置buf的limit的位置为capacity */ public abstract ByteBuf clear(); /** * Marks the current {@code readerIndex} in this buffer. You can * reposition the current {@code readerIndex} to the marked * {@code readerIndex} by calling {@link #resetReaderIndex()}. * The initial value of the marked {@code readerIndex} is {@code 0}. 标记当前buf的读索引。我们可以调用#resetReaderIndex方法,重回标记的读索引位置。 初始标记位置为0。 */ public abstract ByteBuf markReaderIndex(); /** * Repositions the current {@code readerIndex} to the marked * {@code readerIndex} in this buffer. *重回标记的读索引位置 * @throws IndexOutOfBoundsException * if the current {@code writerIndex} is less than the marked * {@code readerIndex} */ public abstract ByteBuf resetReaderIndex(); /** * Marks the current {@code writerIndex} in this buffer. You can * reposition the current {@code writerIndex} to the marked * {@code writerIndex} by calling {@link #resetWriterIndex()}. * The initial value of the marked {@code writerIndex} is {@code 0}. 标记当前buf的写索引。我们可以调用#resetWriterIndex方法,重回标记的写索引位置。 初始标记位置为0。 */ public abstract ByteBuf markWriterIndex(); /** * Repositions the current {@code writerIndex} to the marked * {@code writerIndex} in this buffer. *重回标记的写索引位置 * @throws IndexOutOfBoundsException * if the current {@code readerIndex} is greater than the marked * {@code writerIndex} */ public abstract ByteBuf resetWriterIndex(); /** * Discards the bytes between the 0th index and {@code readerIndex}. * It moves the bytes between {@code readerIndex} and {@code writerIndex} * to the 0th index, and sets {@code readerIndex} and {@code writerIndex} * to {@code 0} and {@code oldWriterIndex - oldReaderIndex} respectively. 丢弃0索引到当前读索引的数据。并移到读索引到写索引之间的数据,到0索引位置上, 重置读索引为0,写索引为oldWriterIndex - oldReaderIndex * <p> * Please refer to the class documentation for more detailed explanation. 更详细的扩展,请参考具体的class文档 */ public abstract ByteBuf discardReadBytes(); /** * Similar to {@link ByteBuf#discardReadBytes()} except that this method might discard * some, all, or none of read bytes depending on its internal implementation to reduce * overall memory bandwidth consumption at the cost of potentially additional memory * consumption. 与ByteBuf#discardReadBytes方法相似,此方可能会在内存出现负载时,丢弃一些或所有, 或不丢弃可读字节数据,具体依赖具体的实现,以减少内存的使用量。 */ public abstract ByteBuf discardSomeReadBytes(); /** * Makes sure the number of {@linkplain #writableBytes() the writable bytes} * is equal to or greater than the specified value. If there is enough * writable bytes in this buffer, this method returns with no side effect. * Otherwise, it raises an {@link IllegalArgumentException}. 确保当前buf可以容下minWritableBytes个字节数据,如果buf足够写,则方法返回没有任何影响, 否则抛出非法参数异常 * * @param minWritableBytes * the expected minimum number of writable bytes * @throws IndexOutOfBoundsException * if {@link #writerIndex()} + {@code minWritableBytes} > {@link #maxCapacity()} */ public abstract ByteBuf ensureWritable(int minWritableBytes); /** * Tries to make sure the number of {@linkplain #writableBytes() the writable bytes} * is equal to or greater than the specified value. Unlike {@link #ensureWritable(int)}, * this method does not raise an exception but returns a code. *尝试确保buf可以写minWritableBytes字节数据。与#ensureWritable(int)方法不同的时,不会抛出异常 * @param minWritableBytes * the expected minimum number of writable bytes * @param force * When {@link #writerIndex()} + {@code minWritableBytes} > {@link #maxCapacity()}: * [list] * [*]{@code true} - the capacity of the buffer is expanded to {@link #maxCapacity()} * [*]{@code false} - the capacity of the buffer is unchanged 当force为true,空间不足时,扩展buf容量为最大容量; false表示,空间不足时,容量没有任何改变 * [/list] * @return {@code 0} if the buffer has enough writable bytes, and its capacity is unchanged. * {@code 1} if the buffer does not have enough bytes, and its capacity is unchanged. * {@code 2} if the buffer has enough writable bytes, and its capacity has been increased. * {@code 3} if the buffer does not have enough bytes, but its capacity has been * increased to its maximum. 返回代码0,表示buf可以容下minWritableBytes个字节数据; 1表示,没有足够的空间可写,容量没有变化; 2表示,buf可以容下minWritableBytes个字节数据,容量扩展; 3表示,buf空间不够,容量扩展至最大值。 */ public abstract int ensureWritable(int minWritableBytes, boolean force); /** * Gets a byte at the specified absolute {@code index} in this buffer. * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. * 获取指定索引位置的字节,此方法不会修改读写索引 * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * {@code index + 1} is greater than {@code this.capacity} */ public abstract byte getByte(int index); /** * Transfers this buffer's data to the specified destination starting at * the specified absolute {@code index} until the destination becomes * non-writable. This method is basically same with * {@link #getBytes(int, ByteBuf, int, int)}, except that this * method increases the {@code writerIndex} of the destination by the * number of the transferred bytes while * {@link #getBytes(int, ByteBuf, int, int)} does not. * This method does not modify {@code readerIndex} or {@code writerIndex} of * the source buffer (i.e. {@code this}). *从当前buf的index绝对索引开始,转移当前buf的数据到dst buf中。此方法与#getBytes(int, ByteBuf, int, int)方法相似, 不同的时,此方法将会改变dst buf的写索引,而#getBytes(int, ByteBuf, int, int)不会。此方法不会改变当前buf的 读写索引。 * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * if {@code index + dst.writableBytes} is greater than * {@code this.capacity} */ public abstract ByteBuf getBytes(int index, ByteBuf dst); /** * Transfers this buffer's data to the specified destination starting at * the specified absolute {@code index}. This method is basically same * with {@link #getBytes(int, ByteBuf, int, int)}, except that this * method increases the {@code writerIndex} of the destination by the * number of the transferred bytes while * {@link #getBytes(int, ByteBuf, int, int)} does not. * This method does not modify {@code readerIndex} or {@code writerIndex} of * the source buffer (i.e. {@code this}). *与上面方法不同的是,转移的数据的长度为length * @param length the number of bytes to transfer * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0}, * if {@code index + length} is greater than * {@code this.capacity}, or * if {@code length} is greater than {@code dst.writableBytes} */ public abstract ByteBuf getBytes(int index, ByteBuf dst, int length); /** * Transfers this buffer's data to the specified destination starting at * the specified absolute {@code index}. * This method does not modify {@code readerIndex} or {@code writerIndex} * of both the source (i.e. {@code this}) and the destination. *从当前buf的绝对索引index开始,转移length长度的数据到dst buf中,dstIndex绝对索引开始, 此方法不会修改源buf和目的buf的读写索引位置。 * @param dstIndex the first index of the destination * @param length the number of bytes to transfer * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0}, * if the specified {@code dstIndex} is less than {@code 0}, * if {@code index + length} is greater than * {@code this.capacity}, or * if {@code dstIndex + length} is greater than * {@code dst.capacity} */ public abstract ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length); /** * Transfers this buffer's data to the specified destination starting at * the specified absolute {@code index}. * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer *从当前buf的绝对index开始,转移数据到,目的dst 字节数据中,此方法不会修改当前buf的读写索引。 * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * if {@code index + dst.length} is greater than * {@code this.capacity} */ public abstract ByteBuf getBytes(int index, byte[] dst); /** * Transfers this buffer's data to the specified destination starting at * the specified absolute {@code index}. * This method does not modify {@code readerIndex} or {@code writerIndex} * of this buffer. *与上面方法是,转移的字节长度为length,从目的字节数组的dstIndex索引开始 * @param dstIndex the first index of the destination * @param length the number of bytes to transfer * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0}, * if the specified {@code dstIndex} is less than {@code 0}, * if {@code index + length} is greater than * {@code this.capacity}, or * if {@code dstIndex + length} is greater than * {@code dst.length} */ public abstract ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length); /** * Transfers this buffer's data to the specified destination starting at * the specified absolute {@code index} until the destination's position * reaches its limit. * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer while the destination's {@code position} will be increased. *从当前buf的绝对索引index开始,转移数据到目的nio buf中,直至到达目的nio buf的limit的位置 ,此方法不会修改当前buf的读写索引,会修改nio buf的位置索引position * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * if {@code index + dst.remaining()} is greater than * {@code this.capacity} */ public abstract ByteBuf getBytes(int index, ByteBuffer dst); /** * Transfers this buffer's data to the specified stream starting at the * specified absolute {@code index}. * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. *从当前buf的绝对索引index开始,转移数据到目的OutputStream中,直至到达目的nio buf的limit的位置 ,此方法不会修改当前buf的读写索引 * @param length the number of bytes to transfer * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * if {@code index + length} is greater than * {@code this.capacity} * @throws IOException * if the specified stream threw an exception during I/O */ public abstract ByteBuf getBytes(int index, OutputStream out, int length) throws IOException; /** * Transfers this buffer's data to the specified channel starting at the * specified absolute {@code index}. * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. *从当前buf的绝对索引index开始,转移数据到目的聚集字节通道GatheringByteChannel中, ,此方法不会修改当前buf的读写索引 * @param length the maximum number of bytes to transfer * * @return the actual number of bytes written out to the specified channel * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * if {@code index + length} is greater than * {@code this.capacity} * @throws IOException * if the specified channel threw an exception during I/O */ public abstract int getBytes(int index, GatheringByteChannel out, int length) throws IOException; /** * Transfers this buffer's data starting at the specified absolute {@code index} * to the specified channel starting at the given file position. * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. This method does not modify the channel's position. *从当前buf的绝对索引index开始,转移数据到目的文件域FileChannel中, 此方法不会修改当前buf的读写索引,同时不会修改文件域的位置索引position * @param position the file position at which the transfer is to begin * @param length the maximum number of bytes to transfer * * @return the actual number of bytes written out to the specified channel * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * if {@code index + length} is greater than * {@code this.capacity} * @throws IOException * if the specified channel threw an exception during I/O */ public abstract int getBytes(int index, FileChannel out, long position, int length) throws IOException; /** * Gets a {@link CharSequence} with the given length at the given index. *从buf的index索引开始,获取给定长度字符序列 * @param length the length to read * @param charset that should be used * @return the sequence * @throws IndexOutOfBoundsException * if {@code length} is greater than {@code this.readableBytes} */ public abstract CharSequence getCharSequence(int index, int length, Charset charset); /** * Sets the specified byte at the specified absolute {@code index} in this * buffer. The 24 high-order bits of the specified value are ignored. * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. *从buf的索引index开始,设置特殊的字节,一些特殊值的高24位将会被忽略,不会修改buf的读写索引 * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * {@code index + 1} is greater than {@code this.capacity} */ public abstract ByteBuf setByte(int index, int value); /** * Transfers the specified source buffer's data to this buffer starting at * the specified absolute {@code index} until the source buffer becomes * unreadable. This method is basically same with * {@link #setBytes(int, ByteBuf, int, int)}, except that this * method increases the {@code readerIndex} of the source buffer by * the number of the transferred bytes while * {@link #setBytes(int, ByteBuf, int, int)} does not. * This method does not modify {@code readerIndex} or {@code writerIndex} of * the source buffer (i.e. {@code this}). *从源buf转移数据到当前buf的绝对索引index上,直到源buf不可读。此方法与setBytes(int, ByteBuf, int, int) 相同,不同的时此方法会增加源buf的索引,而setBytes(int, ByteBuf, int, int)不会。 此方法不为修改源buf的读写索引 * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * if {@code index + src.readableBytes} is greater than * {@code this.capacity} */ public abstract ByteBuf setBytes(int index, ByteBuf src); /** * Transfers the specified source buffer's data to this buffer starting at * the specified absolute {@code index}. This method is basically same * with {@link #setBytes(int, ByteBuf, int, int)}, except that this * method increases the {@code readerIndex} of the source buffer by * the number of the transferred bytes while * {@link #setBytes(int, ByteBuf, int, int)} does not. * This method does not modify {@code readerIndex} or {@code writerIndex} of * the source buffer (i.e. {@code this}). *与上面不同的时,从源buf转移指定长度的数据 * @param length the number of bytes to transfer * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0}, * if {@code index + length} is greater than * {@code this.capacity}, or * if {@code length} is greater than {@code src.readableBytes} */ public abstract ByteBuf setBytes(int index, ByteBuf src, int length); /** * Transfers the specified source buffer's data to this buffer starting at * the specified absolute {@code index}. * This method does not modify {@code readerIndex} or {@code writerIndex} * of both the source (i.e. {@code this}) and the destination. *与上面个方法不同的是,此方法是从源buf的srcIndex索引开始读数据,并且不会修改源buf和 目的buf的索引。 * @param srcIndex the first index of the source * @param length the number of bytes to transfer * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0}, * if the specified {@code srcIndex} is less than {@code 0}, * if {@code index + length} is greater than * {@code this.capacity}, or * if {@code srcIndex + length} is greater than * {@code src.capacity} */ public abstract ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length); /** * Transfers the specified source array's data to this buffer starting at * the specified absolute {@code index}. * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. *转移源字节数组中的数据到当前buf的index位置,不会修改当前buf的索引。 * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * if {@code index + src.length} is greater than * {@code this.capacity} */ public abstract ByteBuf setBytes(int index, byte[] src); /** * Transfers the specified source array's data to this buffer starting at * the specified absolute {@code index}. * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. *与上面不同的是此方法是从源buf的srcIndex索引开始读数据,并且字节长度为length * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0}, * if the specified {@code srcIndex} is less than {@code 0}, * if {@code index + length} is greater than * {@code this.capacity}, or * if {@code srcIndex + length} is greater than {@code src.length} */ public abstract ByteBuf setBytes(int index, byte[] src, int srcIndex, int length); /** * Transfers the specified source buffer's data to this buffer starting at * the specified absolute {@code index} until the source buffer's position * reaches its limit. * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. *转移nio ByteBuffer中的数据到当前buf,直到位置索引到达limit位置,此方法不会修改读写索引 * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * if {@code index + src.remaining()} is greater than * {@code this.capacity} */ public abstract ByteBuf setBytes(int index, ByteBuffer src); /** * Transfers the content of the specified source stream to this buffer * starting at the specified absolute {@code index}. * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. *转移目的输入流的数据到当前buf,,此方法不会修改读写索引 * @param length the number of bytes to transfer * * @return the actual number of bytes read in from the specified channel. * {@code -1} if the specified channel is closed. * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * if {@code index + length} is greater than {@code this.capacity} * @throws IOException * if the specified stream threw an exception during I/O */ public abstract int setBytes(int index, InputStream in, int length) throws IOException; /** * Transfers the content of the specified source channel to this buffer * starting at the specified absolute {@code index}. * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. *转移目的分散字节通道的数据到当前buf,,此方法不会修改读写索引 * @param length the maximum number of bytes to transfer * * @return the actual number of bytes read in from the specified channel. * {@code -1} if the specified channel is closed. * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * if {@code index + length} is greater than {@code this.capacity} * @throws IOException * if the specified channel threw an exception during I/O */ public abstract int setBytes(int index, ScatteringByteChannel in, int length) throws IOException; /** * Transfers the content of the specified source channel starting at the given file position * to this buffer starting at the specified absolute {@code index}. * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. This method does not modify the channel's position. *转移目的文件通道的数据到当前buf,,此方法不会修改读写索引 * @param position the file position at which the transfer is to begin * @param length the maximum number of bytes to transfer * * @return the actual number of bytes read in from the specified channel. * {@code -1} if the specified channel is closed. * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * if {@code index + length} is greater than {@code this.capacity} * @throws IOException * if the specified channel threw an exception during I/O */ public abstract int setBytes(int index, FileChannel in, long position, int length) throws IOException; /** * Fills this buffer with <tt>NUL (0x00)</tt> starting at the specified * absolute {@code index}. * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. *从buf的index位置,填充字节buf为NUL (0x00),此方法不会修改当前buf中的索引位置 * @param length the number of <tt>NUL</tt>s to write to the buffer * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * if {@code index + length} is greater than {@code this.capacity} */ public abstract ByteBuf setZero(int index, int length); /** * Writes the specified {@link CharSequence} at the current {@code writerIndex} and increases * the {@code writerIndex} by the written bytes. *从当前写索引位置开始,写字符序列到当前buf,并更新写索引 * @param index on which the sequence should be written * @param sequence to write * @param charset that should be used. * @return the written number of bytes. * @throws IndexOutOfBoundsException * if {@code this.writableBytes} is not large enough to write the whole sequence */ public abstract int setCharSequence(int index, CharSequence sequence, Charset charset); /** * Gets a byte at the current {@code readerIndex} and increases * the {@code readerIndex} by {@code 1} in this buffer. * 从buf当前的读索引开始,读取一个字节数据,读索引向前移一位 * @throws IndexOutOfBoundsException * if {@code this.readableBytes} is less than {@code 1} */ public abstract byte readByte(); /** * Transfers this buffer's data to a newly created buffer starting at * the current {@code readerIndex} and increases the {@code readerIndex} * by the number of the transferred bytes (= {@code length}). * The returned buffer's {@code readerIndex} and {@code writerIndex} are * {@code 0} and {@code length} respectively. *从当前buf的读索引开始转移length字节数据到新创建的buf中,并增加当前buf的读索引, 新创建的buf的读索引为0,写索引为length * @param length the number of bytes to transfer * * @return the newly created buffer which contains the transferred bytes * * @throws IndexOutOfBoundsException * if {@code length} is greater than {@code this.readableBytes} */ public abstract ByteBuf readBytes(int length); /** * Returns a new slice of this buffer's sub-region starting at the current * {@code readerIndex} and increases the {@code readerIndex} by the size * of the new slice (= {@code length}). 返回当前buf的读索引开始,长度为length的字节切片 * <p> * Also be aware that this method will NOT call {@link #retain()} and so the * reference count will NOT be increased. * 注意此方法不会调用retain方法,索引buf的引用计数器不会变 * @param length the size of the new slice * * @return the newly created slice * * @throws IndexOutOfBoundsException * if {@code length} is greater than {@code this.readableBytes} */ public abstract ByteBuf readSlice(int length); /** * Returns a new retained slice of this buffer's sub-region starting at the current * {@code readerIndex} and increases the {@code readerIndex} by the size * of the new slice (= {@code length}). * <p> * Note that this method returns a {@linkplain #retain() retained} buffer unlike {@link #readSlice(int)}. * This method behaves similarly to {@code readSlice(...).retain()} except that this method may return * a buffer implementation that produces less garbage. *与上面方法不同的时,会增加buf的引用计数器,会产生少量的垃圾 * @param length the size of the new slice * * @return the newly created slice * * @throws IndexOutOfBoundsException * if {@code length} is greater than {@code this.readableBytes} */ public abstract ByteBuf readRetainedSlice(int length); /** * Transfers this buffer's data to the specified destination starting at * the current {@code readerIndex} until the destination becomes * non-writable, and increases the {@code readerIndex} by the number of the * transferred bytes. This method is basically same with * {@link #readBytes(ByteBuf, int, int)}, except that this method * increases the {@code writerIndex} of the destination by the number of * the transferred bytes while {@link #readBytes(ByteBuf, int, int)} * does not. *从当前buf的读索引开始,转移数据到目的buf,直到当前buf不可读,同时更新当前buf的读索引。 此方法,与#readBytes(ByteBuf, int, int)基本相同,不同的是此方法会增加目的字节buf的写索引, 而#readBytes(ByteBuf, int, int)不会。 * @throws IndexOutOfBoundsException * if {@code dst.writableBytes} is greater than * {@code this.readableBytes} */ public abstract ByteBuf readBytes(ByteBuf dst); /** * Transfers this buffer's data to the specified destination starting at * the current {@code readerIndex} and increases the {@code readerIndex} * by the number of the transferred bytes (= {@code length}). This method * is basically same with {@link #readBytes(ByteBuf, int, int)}, * except that this method increases the {@code writerIndex} of the * destination by the number of the transferred bytes (= {@code length}) * while {@link #readBytes(ByteBuf, int, int)} does not. *与上面方法不同到的是,从当前buf读取指定长度的字节数据 * @throws IndexOutOfBoundsException * if {@code length} is greater than {@code this.readableBytes} or * if {@code length} is greater than {@code dst.writableBytes} */ public abstract ByteBuf readBytes(ByteBuf dst, int length); /** * Transfers this buffer's data to the specified destination starting at * the current {@code readerIndex} and increases the {@code readerIndex} * by the number of the transferred bytes (= {@code length}). *此方法,与上面方法不同的是,将当前buf的数据放到目的buf的dstIndex位置,同时, 此方法不会修改目的buf的写索引 * @param dstIndex the first index of the destination * @param length the number of bytes to transfer * * @throws IndexOutOfBoundsException * if the specified {@code dstIndex} is less than {@code 0}, * if {@code length} is greater than {@code this.readableBytes}, or * if {@code dstIndex + length} is greater than * {@code dst.capacity} */ public abstract ByteBuf readBytes(ByteBuf dst, int dstIndex, int length); /** * Transfers this buffer's data to the specified destination starting at * the current {@code readerIndex} and increases the {@code readerIndex} * by the number of the transferred bytes (= {@code dst.length}). *从当前buf的读索引开始,转移数据到目的字节数组中 * @throws IndexOutOfBoundsException * if {@code dst.length} is greater than {@code this.readableBytes} */ public abstract ByteBuf readBytes(byte[] dst); /** * Transfers this buffer's data to the specified destination starting at * the current {@code readerIndex} and increases the {@code readerIndex} * by the number of the transferred bytes (= {@code length}). *与上面方法不同的是,转移字节长度为length,并方法目的字节数组的dstIndex上 * @param dstIndex the first index of the destination * @param length the number of bytes to transfer * * @throws IndexOutOfBoundsException * if the specified {@code dstIndex} is less than {@code 0}, * if {@code length} is greater than {@code this.readableBytes}, or * if {@code dstIndex + length} is greater than {@code dst.length} */ public abstract ByteBuf readBytes(byte[] dst, int dstIndex, int length); /** * Transfers this buffer's data to the specified destination starting at * the current {@code readerIndex} until the destination's position * reaches its limit, and increases the {@code readerIndex} by the * number of the transferred bytes. *从当前buf的读索引开始,转移数据到java nio ByteBuffer中,同时会更新当前buf的读索引 * @throws IndexOutOfBoundsException * if {@code dst.remaining()} is greater than * {@code this.readableBytes} */ public abstract ByteBuf readBytes(ByteBuffer dst); /** * Transfers this buffer's data to the specified stream starting at the * current {@code readerIndex}. *从当前buf的读索引开始,转移数据到输出流OutputStream中 * @param length the number of bytes to transfer * * @throws IndexOutOfBoundsException * if {@code length} is greater than {@code this.readableBytes} * @throws IOException * if the specified stream threw an exception during I/O */ public abstract ByteBuf readBytes(OutputStream out, int length) throws IOException; /** * Transfers this buffer's data to the specified stream starting at the * current {@code readerIndex}. *从当前buf的读索引开始,转移数据到目的聚集通道中 * @param length the maximum number of bytes to transfer * * @return the actual number of bytes written out to the specified channel * * @throws IndexOutOfBoundsException * if {@code length} is greater than {@code this.readableBytes} * @throws IOException * if the specified channel threw an exception during I/O */ public abstract int readBytes(GatheringByteChannel out, int length) throws IOException; /** * Gets a {@link CharSequence} with the given length at the current {@code readerIndex} * and increases the {@code readerIndex} by the given length. *从当前buf的读索引开始,转移length长度的字节数据到目的字符序列中,同时会更新当前buf的读索引 * @param length the length to read * @param charset that should be used * @return the sequence * @throws IndexOutOfBoundsException * if {@code length} is greater than {@code this.readableBytes} */ public abstract CharSequence readCharSequence(int length, Charset charset); /** * Transfers this buffer's data starting at the current {@code readerIndex} * to the specified channel starting at the given file position. * This method does not modify the channel's position. *从当前buf的读索引开始,转移数据到目的文件通道中,不会修改文件通道的位置 * @param position the file position at which the transfer is to begin * @param length the maximum number of bytes to transfer * * @return the actual number of bytes written out to the specified channel * * @throws IndexOutOfBoundsException * if {@code length} is greater than {@code this.readableBytes} * @throws IOException * if the specified channel threw an exception during I/O */ public abstract int readBytes(FileChannel out, long position, int length) throws IOException; /** * Increases the current {@code readerIndex} by the specified * {@code length} in this buffer. *增加读索引位置length长度,向前移动length位置 * @throws IndexOutOfBoundsException * if {@code length} is greater than {@code this.readableBytes} */ public abstract ByteBuf skipBytes(int length); /** * Sets the specified boolean at the current {@code writerIndex} * and increases the {@code writerIndex} by {@code 1} in this buffer. * 从buf当前写索引位置写一个布尔值,写索引向前移一位 * @throws IndexOutOfBoundsException * if {@code this.writableBytes} is less than {@code 1} */ public abstract ByteBuf writeBoolean(boolean value); /** * Sets the specified byte at the current {@code writerIndex} * and increases the {@code writerIndex} by {@code 1} in this buffer. * The 24 high-order bits of the specified value are ignored. * 从buf当前写索引位置写一个字节,写索引向前移一位。 一些特殊值的高24位将会被忽略 * @throws IndexOutOfBoundsException * if {@code this.writableBytes} is less than {@code 1} */ public abstract ByteBuf writeByte(int value); /** * Transfers the specified source buffer's data to this buffer starting at * the current {@code writerIndex} until the source buffer becomes * unreadable, and increases the {@code writerIndex} by the number of * the transferred bytes. This method is basically same with * {@link #writeBytes(ByteBuf, int, int)}, except that this method * increases the {@code readerIndex} of the source buffer by the number of * the transferred bytes while {@link #writeBytes(ByteBuf, int, int)} * does not. *从当前buf写索引开始,转移源buf中的数据到当前buf的中,直到源buf不可读,同时更新当前buf的写索引, 此方法与#writeBytes(ByteBuf, int, int)基本相同,除了此方法回修改源buf的读索引,而#writeBytes(ByteBuf, int, int) 不会。 * @throws IndexOutOfBoundsException * if {@code src.readableBytes} is greater than * {@code this.writableBytes} */ public abstract ByteBuf writeBytes(ByteBuf src); /** * Transfers the specified source buffer's data to this buffer starting at * the current {@code writerIndex} and increases the {@code writerIndex} * by the number of the transferred bytes (= {@code length}). This method * is basically same with {@link #writeBytes(ByteBuf, int, int)}, * except that this method increases the {@code readerIndex} of the source * buffer by the number of the transferred bytes (= {@code length}) while * {@link #writeBytes(ByteBuf, int, int)} does not. * 与上面方法不同的时,限制源buf转移数据的长度 * @param length the number of bytes to transfer * * @throws IndexOutOfBoundsException * if {@code length} is greater than {@code this.writableBytes} or * if {@code length} is greater then {@code src.readableBytes} */ public abstract ByteBuf writeBytes(ByteBuf src, int length); /** * Transfers the specified source buffer's data to this buffer starting at * the current {@code writerIndex} and increases the {@code writerIndex} * by the number of the transferred bytes (= {@code length}). * 与上面方法不同的是,转移数据从指定索引开始srcIndex * @param srcIndex the first index of the source * @param length the number of bytes to transfer * * @throws IndexOutOfBoundsException * if the specified {@code srcIndex} is less than {@code 0}, * if {@code srcIndex + length} is greater than * {@code src.capacity}, or * if {@code length} is greater than {@code this.writableBytes} */ public abstract ByteBuf writeBytes(ByteBuf src, int srcIndex, int length); /** * Transfers the specified source array's data to this buffer starting at * the current {@code writerIndex} and increases the {@code writerIndex} * by the number of the transferred bytes (= {@code src.length}). * 写字节数组中的数据到当前buf,并更新当前buf的写索引 * @throws IndexOutOfBoundsException * if {@code src.length} is greater than {@code this.writableBytes} */ public abstract ByteBuf writeBytes(byte[] src); /** * Transfers the specified source array's data to this buffer starting at * the current {@code writerIndex} and increases the {@code writerIndex} * by the number of the transferred bytes (= {@code length}). *与上面方法不同的时,限定了字节数组的开始索引 * @param srcIndex the first index of the source * @param length the number of bytes to transfer * * @throws IndexOutOfBoundsException * if the specified {@code srcIndex} is less than {@code 0}, * if {@code srcIndex + length} is greater than * {@code src.length}, or * if {@code length} is greater than {@code this.writableBytes} */ public abstract ByteBuf writeBytes(byte[] src, int srcIndex, int length); /** * Transfers the specified source buffer's data to this buffer starting at * the current {@code writerIndex} until the source buffer's position * reaches its limit, and increases the {@code writerIndex} by the * number of the transferred bytes. 写java nio ByteBuffer中的数据到当前buf,直到ByteBuffer的位置索引到limit位置,同时更新写索引 * * @throws IndexOutOfBoundsException * if {@code src.remaining()} is greater than * {@code this.writableBytes} */ public abstract ByteBuf writeBytes(ByteBuffer src); /** * Transfers the content of the specified stream to this buffer * starting at the current {@code writerIndex} and increases the * {@code writerIndex} by the number of the transferred bytes. *写输入流InputStream中的length个字节数据到当前buf,同时更新写索引 * @param length the number of bytes to transfer * * @return the actual number of bytes read in from the specified stream * * @throws IndexOutOfBoundsException * if {@code length} is greater than {@code this.writableBytes} * @throws IOException * if the specified stream threw an exception during I/O */ public abstract int writeBytes(InputStream in, int length) throws IOException; /** * Transfers the content of the specified channel to this buffer * starting at the current {@code writerIndex} and increases the * {@code writerIndex} by the number of the transferred bytes. *写分散字节通道ScatteringByteChannel中的length个字节数据到当前buf,同时更新写索引 * @param length the maximum number of bytes to transfer * * @return the actual number of bytes read in from the specified channel * * @throws IndexOutOfBoundsException * if {@code length} is greater than {@code this.writableBytes} * @throws IOException * if the specified channel threw an exception during I/O */ public abstract int writeBytes(ScatteringByteChannel in, int length) throws IOException; /** * Transfers the content of the specified channel starting at the given file position * to this buffer starting at the current {@code writerIndex} and increases the * {@code writerIndex} by the number of the transferred bytes. * This method does not modify the channel's position. *写文件FileChannel中的length个字节数据到当前buf,同时更新写索引,不会修改通道的位置索引 * @param position the file position at which the transfer is to begin * @param length the maximum number of bytes to transfer * * @return the actual number of bytes read in from the specified channel * * @throws IndexOutOfBoundsException * if {@code length} is greater than {@code this.writableBytes} * @throws IOException * if the specified channel threw an exception during I/O */ public abstract int writeBytes(FileChannel in, long position, int length) throws IOException; /** * Fills this buffer with <tt>NUL (0x00)</tt> starting at the current * {@code writerIndex} and increases the {@code writerIndex} by the * specified {@code length}. *从当前写索引开始,填充length个NUL (0x00) * @param length the number of <tt>NUL</tt>s to write to the buffer * * @throws IndexOutOfBoundsException * if {@code length} is greater than {@code this.writableBytes} */ public abstract ByteBuf writeZero(int length); /** * Writes the specified {@link CharSequence} at the current {@code writerIndex} and increases * the {@code writerIndex} by the written bytes. * in this buffer. *从当前写索引,写字符序列到当前buf * @param sequence to write * @param charset that should be used * @return the written number of bytes * @throws IndexOutOfBoundsException * if {@code this.writableBytes} is not large enough to write the whole sequence */ public abstract int writeCharSequence(CharSequence sequence, Charset charset); /** * Returns a copy of this buffer's readable bytes. Modifying the content * of the returned buffer or this buffer does not affect each other at all. * This method is identical to {@code buf.copy(buf.readerIndex(), buf.readableBytes())}. * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. 返回当前buf 可读字节的拷贝。修改返回的copy buf,不会影响当前buf。此方法与 buf.copy(buf.readerIndex(), buf.readableBytes())方法相同,不会修改读写索引 */ public abstract ByteBuf copy(); /** * Returns a copy of this buffer's sub-region. Modifying the content of * the returned buffer or this buffer does not affect each other at all. * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. 此方法与上面方法,不同的是,限定了读数据开始索引和读取字节的长度 */ public abstract ByteBuf copy(int index, int length); /** * Returns a slice of this buffer's readable bytes. Modifying the content * of the returned buffer or this buffer affects each other's content * while they maintain separate indexes and marks. This method is * identical to {@code buf.slice(buf.readerIndex(), buf.readableBytes())}. * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. 返回当前buf的可读字节数据的切片slice,当他们维护各自的索引和标记时, 修改返回的切片buf或当前buf,会相互影响buf数据,此方法等同于 buf.slice(buf.readerIndex(), buf.readableBytes()),此方法不会修改读写索引 * <p> * Also be aware that this method will NOT call {@link #retain()} and so the * reference count will NOT be increased. 注意,此方法不会调用retain方法,即不会增加buf的引用计数器 */ public abstract ByteBuf slice(); /** * Returns a slice of this buffer's sub-region. Modifying the content of * the returned buffer or this buffer affects each other's content while * they maintain separate indexes and marks. * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. 此方法与上面方法,不同的是,限定了切片数据开始索引和字节的长度 * <p> * Also be aware that this method will NOT call {@link #retain()} and so the * reference count will NOT be increased. */ public abstract ByteBuf slice(int index, int length); /** * Returns a retained slice of this buffer's readable bytes. Modifying the content * of the returned buffer or this buffer affects each other's content * while they maintain separate indexes and marks. This method is * identical to {@code buf.slice(buf.readerIndex(), buf.readableBytes())}. * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. * <p> * Note that this method returns a {@linkplain #retain() retained} buffer unlike {@link #slice()}. * This method behaves similarly to {@code slice().retain()} except that this method may return * a buffer implementation that produces less garbage. 与#slice方法不同的是,会调用retain方法,即增加buf的引用计数器,同时可能会产生一些内存垃圾 */ public abstract ByteBuf retainedSlice(); /** * Returns a retained slice of this buffer's sub-region. Modifying the content of * the returned buffer or this buffer affects each other's content while * they maintain separate indexes and marks. * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. * <p> * Note that this method returns a {@linkplain #retain() retained} buffer unlike {@link #slice(int, int)}. * This method behaves similarly to {@code slice(...).retain()} except that this method may return * a buffer implementation that produces less garbage. 此方法与上面方法,不同的是,限定了切片数据开始索引和字节的长度 */ public abstract ByteBuf retainedSlice(int index, int length); /** * Returns a buffer which shares the whole region of this buffer. * Modifying the content of the returned buffer or this buffer affects * each other's content while they maintain separate indexes and marks. * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. 返回buf的整个共享域,当他们维护各自的索引和标记时, 修改返回的buf或当前buf,会相互影响buf数据,此方法不会修改读写索引 * <p> * The reader and writer marks will not be duplicated. Also be aware that this method will * NOT call {@link #retain()} and so the reference count will NOT be increased. * @return A buffer whose readable content is equivalent to the buffer returned by {@link #slice()}. * However this buffer will share the capacity of the underlying buffer, and therefore allows access to all of the * underlying content if necessary. 读写标记不会复制。同时此方法不会调用retain方法,即不会增加buf的引用计数器, 返回的buf的可读内容相当于#slice方法返回的buf。不同的是,此方法返回的buf与底层buf共享容量, 因此如果需要,运行方法底层的数据内容 */ public abstract ByteBuf duplicate(); /** * Returns a retained buffer which shares the whole region of this buffer. * Modifying the content of the returned buffer or this buffer affects * each other's content while they maintain separate indexes and marks. * This method is identical to {@code buf.slice(0, buf.capacity())}. * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. * <p> * Note that this method returns a {@linkplain #retain() retained} buffer unlike {@link #slice(int, int)}. * This method behaves similarly to {@code duplicate().retain()} except that this method may return * a buffer implementation that produces less garbage. 与上述方法不同的是,会调用retain方法,即增加buf的引用计数器,同时可能会产生一些内存垃圾 */ public abstract ByteBuf retainedDuplicate(); /** * Returns the maximum number of NIO {@link ByteBuffer}s that consist this buffer. Note that {@link #nioBuffers()} * or {@link #nioBuffers(int, int)} might return a less number of {@link ByteBuffer}s. *返回包含当前buf的最大java nio ByteBuffer数量。注意#nioBuffers和#nioBuffers(int, int)方法,可能 返回更少数量的ByteBuffer * @return {@code -1} if this buffer has no underlying {@link ByteBuffer}. * the number of the underlying {@link ByteBuffer}s if this buffer has at least one underlying * {@link ByteBuffer}. Note that this method does not return {@code 0} to avoid confusion. * 如果当前buf没有底层ByteBuffer,则返回-1。如果当前buf至少有一个ByteBuffer,则返回数量。注意为了避免 冲突,此方法不会返回0。 * @see #nioBuffer() * @see #nioBuffer(int, int) * @see #nioBuffers() * @see #nioBuffers(int, int) */ public abstract int nioBufferCount(); /** * Exposes this buffer's readable bytes as an NIO {@link ByteBuffer}. The returned buffer * shares the content with this buffer, while changing the position and limit of the returned * NIO buffer does not affect the indexes and marks of this buffer. This method is identical * to {@code buf.nioBuffer(buf.readerIndex(), buf.readableBytes())}. This method does not * modify {@code readerIndex} or {@code writerIndex} of this buffer. Please note that the * returned NIO buffer will not see the changes of this buffer if this buffer is a dynamic * buffer and it adjusted its capacity. * 暴露当前buf的可读数据到一个java nio ByteBuffer中。返回的java nio ByteBuffer与当前buf共享数据, 但修改java nio ByteBuffer的位置和limit,不会修改当前buf的索引和标记。 此方法与buf.nioBuffer(buf.readerIndex(), buf.readableBytes()相同。此方法不会修改当前buf的读写索引。 如果当前buf是一个动态的buf,调整buf容量时,java nio ByteBuffer 是看不到容量的改变的。 * @throws UnsupportedOperationException * if this buffer cannot create a {@link ByteBuffer} that shares the content with itself * * @see #nioBufferCount() * @see #nioBuffers() * @see #nioBuffers(int, int) */ public abstract ByteBuffer nioBuffer(); /** * Exposes this buffer's sub-region as an NIO {@link ByteBuffer}. The returned buffer * shares the content with this buffer, while changing the position and limit of the returned * NIO buffer does not affect the indexes and marks of this buffer. This method does not * modify {@code readerIndex} or {@code writerIndex} of this buffer. Please note that the * returned NIO buffer will not see the changes of this buffer if this buffer is a dynamic * buffer and it adjusted its capacity. *与上面不同的时,限定了共享region的开始索引和数据长度 * @throws UnsupportedOperationException * if this buffer cannot create a {@link ByteBuffer} that shares the content with itself * * @see #nioBufferCount() * @see #nioBuffers() * @see #nioBuffers(int, int) */ public abstract ByteBuffer nioBuffer(int index, int length); /** * Internal use only: Exposes the internal NIO buffer. 内部使用,暴露一个内部的nio buf */ public abstract ByteBuffer internalNioBuffer(int index, int length); /** * Exposes this buffer's readable bytes as an NIO {@link ByteBuffer}'s. The returned buffer * shares the content with this buffer, while changing the position and limit of the returned * NIO buffer does not affect the indexes and marks of this buffer. This method does not * modify {@code readerIndex} or {@code writerIndex} of this buffer. Please note that the * returned NIO buffer will not see the changes of this buffer if this buffer is a dynamic * buffer and it adjusted its capacity. * *与#nioBuffer方法不同的是返回的是一个nio buf数组 * @throws UnsupportedOperationException * if this buffer cannot create a {@link ByteBuffer} that shares the content with itself * * @see #nioBufferCount() * @see #nioBuffer() * @see #nioBuffer(int, int) */ public abstract ByteBuffer[] nioBuffers(); /** * Exposes this buffer's bytes as an NIO {@link ByteBuffer}'s for the specified index and length * The returned buffer shares the content with this buffer, while changing the position and limit * of the returned NIO buffer does not affect the indexes and marks of this buffer. This method does * not modify {@code readerIndex} or {@code writerIndex} of this buffer. Please note that the * returned NIO buffer will not see the changes of this buffer if this buffer is a dynamic * buffer and it adjusted its capacity. *与上面不同的时,限定了共享region的开始索引和数据长度 * @throws UnsupportedOperationException * if this buffer cannot create a {@link ByteBuffer} that shares the content with itself * * @see #nioBufferCount() * @see #nioBuffer() * @see #nioBuffer(int, int) */ public abstract ByteBuffer[] nioBuffers(int index, int length); /** * Returns {@code true} if and only if this buffer has a backing byte array. * If this method returns true, you can safely call {@link #array()} and * {@link #arrayOffset()}. 当前仅当,buf由于有一个backing 字节数组,返回true。如果方法返回true,则可以调用 #array() 和 #arrayOffset()方法. */ public abstract boolean hasArray(); /** * Returns the backing byte array of this buffer. *返回当前buf的backing字节数组 * @throws UnsupportedOperationException * if there no accessible backing byte array */ public abstract byte[] array(); /** * Returns the offset of the first byte within the backing byte array of * this buffer. *返回当前buf backing数组第一个字节在buf中的位置 * @throws UnsupportedOperationException * if there no accessible backing byte array */ public abstract int arrayOffset(); /** * Returns {@code true} if and only if this buffer has a reference to the low-level memory address that points * to the backing data. 当且仅当,当前buf有一个指向backing数据的低位内存地址引用时,返回true */ public abstract boolean hasMemoryAddress(); /** * Returns the low-level memory address that point to the first byte of ths backing data. * 返回buf中第一个字节的低位内存地址 * @throws UnsupportedOperationException * if this buffer does not support accessing the low-level memory address */ public abstract long memoryAddress(); /** * Decodes this buffer's readable bytes into a string with the specified * character set name. This method is identical to * {@code buf.toString(buf.readerIndex(), buf.readableBytes(), charsetName)}. * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. *解码可读字节数据为,更定字符编码的字符串,此方法相当与 buf.toString(buf.readerIndex(), buf.readableBytes(), charsetName), 此方法不会修改读写索引。 * @throws UnsupportedCharsetException * if the specified character set name is not supported by the * current VM */ public abstract String toString(Charset charset); /** * Decodes this buffer's sub-region into a string with the specified * character set. This method does not modify {@code readerIndex} or * {@code writerIndex} of this buffer. 此方法与上面方法,不同的是,限定了buf数据开始索引和字节的长度 */ public abstract String toString(int index, int length, Charset charset); /** * Returns a hash code which was calculated from the content of this * buffer. If there's a byte array which is * {@linkplain #equals(Object) equal to} this array, both arrays should * return the same value. 返回buf内容的hash code。如果buf的字节数组相等,则返回相同hash code */ @Override public abstract int hashCode(); /** * Determines if the content of the specified buffer is identical to the * content of this array. 'Identical' here means: * [list] * [*]the size of the contents of the two buffers are same and * [*]every single byte of the content of the two buffers are same. * [/list] * Please note that it does not compare {@link #readerIndex()} nor * {@link #writerIndex()}. This method also returns {@code false} for * {@code null} and an object which is not an instance of * {@link ByteBuf} type. 判断对象是否想定,当且仅当两个buf中的所有的字节相等,则对象相等,不比较索引, 如果对象不是字节buf,则返回false */ @Override public abstract boolean equals(Object obj); /** * Compares the content of the specified buffer to the content of this * buffer. Comparison is performed in the same manner with the string * comparison functions of various languages such as {@code strcmp}, * {@code memcmp} and {@link String#compareTo(String)}. 比较buf,以字符串的比较形式 */ @Override public abstract int compareTo(ByteBuf buffer); /** * Returns the string representation of this buffer. This method does not * necessarily return the whole content of the buffer but returns * the values of the key properties such as {@link #readerIndex()}, * {@link #writerIndex()} and {@link #capacity()}. 返回buf所表示的字符串,从读索引到写索引位置 */ @Override public abstract String toString(); //增加字节buf引用计数器,增量为increment @Override public abstract ByteBuf retain(int increment); //自增字节buf引用计数器 @Override public abstract ByteBuf retain(); @Override public abstract ByteBuf touch(); //调试时,记录buf操作的相关信息,以便分析内存泄漏问题 @Override public abstract ByteBuf touch(Object hint); }
总结:
对象引用计数器ReferenceCounted,主要记录对象的引用数量,当引用数量为0时,表示可以回收对象,在调试模式下,如果发现对象出现内存泄漏,可以用touch方法记录操作的相关信息,通过ResourceLeakDetector获取操作的相关信息,以便分析内存泄漏的原因。
字节缓存ByteBuf继承了对象引用计数器ReferenceCounted,拥有一个最大容量限制,如果用户尝试用 #capacity(int)和 #ensureWritable(int)方法,增加buf容量超过最大容量,将会抛出非法参数异常;字节buf有两个索引,一个为读索引readerIndex,一个为写索引writerIndex,读索引不能大于写索引,写索引不能小于读索引,buf可读字节数为writerIndex - readerIndex,buf可写字节数为capacity - writerIndex,buf可写的最大字节数为maxCapacity - writerIndex;
可以使用markReader/WriterIndex标记当前buf读写索引位置,resetReader/WriterIndex方法可以重回先前标记的索引位置;
当内存空间负载过度时,我们可以使用discardReadBytes丢弃一些数据,以节省空间;
我们可以使用ensureWritable检测当buf是否有足够的空间写数据;
提供了getBytes方法,可以将buf中的数据转移到目的ByteBuf,Byte数组,Nio字节buf ByteBuffer,OutputStream,聚集字节通道
GatheringByteChannel和文件通道FileChannel中,这些方法不会修改当前buf读写索引,具体是否修改目的对象索引或位置,见java doc 描述。
提供了setBytes方法,可以将源ByteBuf,Byte数组,Nio字节buf ByteBuffer,InputputStream,分散字节通道ScatteringByteChannel和文件通道FileChannel中的数据转移到当前buf中,这些方法不会修改当前buf的读写索引,至于源对象索引或位置,见java doc 描述。
提供了readBytes方法,可以将buf中的数据转移到目的ByteBuf,Byte数组,Nio字节buf ByteBuffer,OutputStream,聚集字节通道GatheringByteChannel和文件通道FileChannel中,这些方法具体会会修改当前buf读索引,至于会不会修改源对象索引或位置,见java doc 描述。
提供了writeBytes方法,可以将源ByteBuf,Byte数组,Nio字节buf ByteBuffer,
InputputStream,分散字节通道ScatteringByteChannel和文件通道FileChannel中的数据写到当前buf中,这些方法会修改当前buf的写索引,至于会不会修改源对象索引或位置,见java
doc 描述。
set*原始类型方法不会修改读写索引;
get*原始类型方法不会修改读写索引;
write*原始类型方法会修改写索引;
read*原始类型方法,会修改读索引;
字节buf中的set/get*方法不会修改当前buf的读写索引,而write*修改写索引,read*会修改读索引;
提供了copy,slice和retainSlice,duplicate和retainedDuplicate方法,用于拷贝,切割,复制当前buf数据,retained*方法会增加buf的引用计数器;
提供nioBuffer和nioBuffers方法,用于包装当前buf可读数据为java nio ByteBuffer和ByteBuffer数组。
附:
下面是字节buf的get*原始类型方法的定义,简单看一下:
下面的方法不会修改读写索引
/** * Gets a boolean at the specified absolute (@code index) in this buffer. * This method does not modify the {@code readerIndex} or {@code writerIndex} * of this buffer. * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * {@code index + 1} is greater than {@code this.capacity} */ public abstract boolean getBoolean(int index); /** * Gets an unsigned byte at the specified absolute {@code index} in this * buffer. This method does not modify {@code readerIndex} or * {@code writerIndex} of this buffer. * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * {@code index + 1} is greater than {@code this.capacity} */ public abstract short getUnsignedByte(int index); /** * Gets a 16-bit short integer at the specified absolute {@code index} in * this buffer. This method does not modify {@code readerIndex} or * {@code writerIndex} of this buffer. * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * {@code index + 2} is greater than {@code this.capacity} */ public abstract short getShort(int index); /** * Gets a 16-bit short integer at the specified absolute {@code index} in * this buffer in Little Endian Byte Order. This method does not modify * {@code readerIndex} or {@code writerIndex} of this buffer. * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * {@code index + 2} is greater than {@code this.capacity} */ public abstract short getShortLE(int index); /** * Gets an unsigned 16-bit short integer at the specified absolute * {@code index} in this buffer. This method does not modify * {@code readerIndex} or {@code writerIndex} of this buffer. * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * {@code index + 2} is greater than {@code this.capacity} */ public abstract int getUnsignedShort(int index); /** * Gets an unsigned 16-bit short integer at the specified absolute * {@code index} in this buffer in Little Endian Byte Order. * This method does not modify {@code readerIndex} or * {@code writerIndex} of this buffer. * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * {@code index + 2} is greater than {@code this.capacity} */ public abstract int getUnsignedShortLE(int index); /** * Gets a 24-bit medium integer at the specified absolute {@code index} in * this buffer. This method does not modify {@code readerIndex} or * {@code writerIndex} of this buffer. * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * {@code index + 3} is greater than {@code this.capacity} */ public abstract int getMedium(int index); /** * Gets a 24-bit medium integer at the specified absolute {@code index} in * this buffer in the Little Endian Byte Order. This method does not * modify {@code readerIndex} or {@code writerIndex} of this buffer. * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * {@code index + 3} is greater than {@code this.capacity} */ public abstract int getMediumLE(int index); /** * Gets an unsigned 24-bit medium integer at the specified absolute * {@code index} in this buffer. This method does not modify * {@code readerIndex} or {@code writerIndex} of this buffer. * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * {@code index + 3} is greater than {@code this.capacity} */ public abstract int getUnsignedMedium(int index); /** * Gets an unsigned 24-bit medium integer at the specified absolute * {@code index} in this buffer in Little Endian Byte Order. * This method does not modify {@code readerIndex} or * {@code writerIndex} of this buffer. * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * {@code index + 3} is greater than {@code this.capacity} */ public abstract int getUnsignedMediumLE(int index); /** * Gets a 32-bit integer at the specified absolute {@code index} in * this buffer. This method does not modify {@code readerIndex} or * {@code writerIndex} of this buffer. * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * {@code index + 4} is greater than {@code this.capacity} */ public abstract int getInt(int index); /** * Gets a 32-bit integer at the specified absolute {@code index} in * this buffer with Little Endian Byte Order. This method does not * modify {@code readerIndex} or {@code writerIndex} of this buffer. * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * {@code index + 4} is greater than {@code this.capacity} */ public abstract int getIntLE(int index); /** * Gets an unsigned 32-bit integer at the specified absolute {@code index} * in this buffer. This method does not modify {@code readerIndex} or * {@code writerIndex} of this buffer. * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * {@code index + 4} is greater than {@code this.capacity} */ public abstract long getUnsignedInt(int index); /** * Gets an unsigned 32-bit integer at the specified absolute {@code index} * in this buffer in Little Endian Byte Order. This method does not * modify {@code readerIndex} or {@code writerIndex} of this buffer. * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * {@code index + 4} is greater than {@code this.capacity} */ public abstract long getUnsignedIntLE(int index); /** * Gets a 64-bit long integer at the specified absolute {@code index} in * this buffer. This method does not modify {@code readerIndex} or * {@code writerIndex} of this buffer. * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * {@code index + 8} is greater than {@code this.capacity} */ public abstract long getLong(int index); /** * Gets a 64-bit long integer at the specified absolute {@code index} in * this buffer in Little Endian Byte Order. This method does not * modify {@code readerIndex} or {@code writerIndex} of this buffer. * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * {@code index + 8} is greater than {@code this.capacity} */ public abstract long getLongLE(int index); /** * Gets a 2-byte UTF-16 character at the specified absolute * {@code index} in this buffer. This method does not modify * {@code readerIndex} or {@code writerIndex} of this buffer. * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * {@code index + 2} is greater than {@code this.capacity} */ public abstract char getChar(int index); /** * Gets a 32-bit floating point number at the specified absolute * {@code index} in this buffer. This method does not modify * {@code readerIndex} or {@code writerIndex} of this buffer. * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * {@code index + 4} is greater than {@code this.capacity} */ public abstract float getFloat(int index); /** * Gets a 64-bit floating point number at the specified absolute * {@code index} in this buffer. This method does not modify * {@code readerIndex} or {@code writerIndex} of this buffer. * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * {@code index + 8} is greater than {@code this.capacity} */ public abstract double getDouble(int index);
下面一些set*原始类型方法从索引index开始,设置原始类型,不会修改读写索引
/** * Sets the specified boolean at the specified absolute {@code index} in this * buffer. * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * {@code index + 1} is greater than {@code this.capacity} */ public abstract ByteBuf setBoolean(int index, boolean value); /** * Sets the specified 16-bit short integer at the specified absolute * {@code index} in this buffer. The 16 high-order bits of the specified * value are ignored. * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * {@code index + 2} is greater than {@code this.capacity} */ public abstract ByteBuf setShort(int index, int value); /** * Sets the specified 16-bit short integer at the specified absolute * {@code index} in this buffer with the Little Endian Byte Order. * The 16 high-order bits of the specified value are ignored. * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * {@code index + 2} is greater than {@code this.capacity} */ public abstract ByteBuf setShortLE(int index, int value); /** * Sets the specified 24-bit medium integer at the specified absolute * {@code index} in this buffer. Please note that the most significant * byte is ignored in the specified value. * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * {@code index + 3} is greater than {@code this.capacity} */ public abstract ByteBuf setMedium(int index, int value); /** * Sets the specified 24-bit medium integer at the specified absolute * {@code index} in this buffer in the Little Endian Byte Order. * Please note that the most significant byte is ignored in the * specified value. * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * {@code index + 3} is greater than {@code this.capacity} */ public abstract ByteBuf setMediumLE(int index, int value); /** * Sets the specified 32-bit integer at the specified absolute * {@code index} in this buffer. * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * {@code index + 4} is greater than {@code this.capacity} */ public abstract ByteBuf setInt(int index, int value); /** * Sets the specified 32-bit integer at the specified absolute * {@code index} in this buffer with Little Endian byte order * . * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * {@code index + 4} is greater than {@code this.capacity} */ public abstract ByteBuf setIntLE(int index, int value); /** * Sets the specified 64-bit long integer at the specified absolute * {@code index} in this buffer. * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * {@code index + 8} is greater than {@code this.capacity} */ public abstract ByteBuf setLong(int index, long value); /** * Sets the specified 64-bit long integer at the specified absolute * {@code index} in this buffer in Little Endian Byte Order. * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * {@code index + 8} is greater than {@code this.capacity} */ public abstract ByteBuf setLongLE(int index, long value); /** * Sets the specified 2-byte UTF-16 character at the specified absolute * {@code index} in this buffer. * The 16 high-order bits of the specified value are ignored. * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * {@code index + 2} is greater than {@code this.capacity} */ public abstract ByteBuf setChar(int index, int value); /** * Sets the specified 32-bit floating-point number at the specified * absolute {@code index} in this buffer. * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * {@code index + 4} is greater than {@code this.capacity} */ public abstract ByteBuf setFloat(int index, float value); /** * Sets the specified 64-bit floating-point number at the specified * absolute {@code index} in this buffer. * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. * * @throws IndexOutOfBoundsException * if the specified {@code index} is less than {@code 0} or * {@code index + 8} is greater than {@code this.capacity} */ public abstract ByteBuf setDouble(int index, double value);
以下一些read*原始类型方法,会修改读索引
/** * Gets a boolean at the current {@code readerIndex} and increases * the {@code readerIndex} by {@code 1} in this buffer. * * @throws IndexOutOfBoundsException * if {@code this.readableBytes} is less than {@code 1} */ public abstract boolean readBoolean(); /** * Gets an unsigned byte at the current {@code readerIndex} and increases * the {@code readerIndex} by {@code 1} in this buffer. * * @throws IndexOutOfBoundsException * if {@code this.readableBytes} is less than {@code 1} */ public abstract short readUnsignedByte(); /** * Gets a 16-bit short integer at the current {@code readerIndex} * and increases the {@code readerIndex} by {@code 2} in this buffer. * * @throws IndexOutOfBoundsException * if {@code this.readableBytes} is less than {@code 2} */ public abstract short readShort(); /** * Gets a 16-bit short integer at the current {@code readerIndex} * in the Little Endian Byte Order and increases the {@code readerIndex} * by {@code 2} in this buffer. * * @throws IndexOutOfBoundsException * if {@code this.readableBytes} is less than {@code 2} */ public abstract short readShortLE(); /** * Gets an unsigned 16-bit short integer at the current {@code readerIndex} * and increases the {@code readerIndex} by {@code 2} in this buffer. * * @throws IndexOutOfBoundsException * if {@code this.readableBytes} is less than {@code 2} */ public abstract int readUnsignedShort(); /** * Gets an unsigned 16-bit short integer at the current {@code readerIndex} * in the Little Endian Byte Order and increases the {@code readerIndex} * by {@code 2} in this buffer. * * @throws IndexOutOfBoundsException * if {@code this.readableBytes} is less than {@code 2} */ public abstract int readUnsignedShortLE(); /** * Gets a 24-bit medium integer at the current {@code readerIndex} * and increases the {@code readerIndex} by {@code 3} in this buffer. * * @throws IndexOutOfBoundsException * if {@code this.readableBytes} is less than {@code 3} */ public abstract int readMedium(); /** * Gets a 24-bit medium integer at the current {@code readerIndex} * in the Little Endian Byte Order and increases the * {@code readerIndex} by {@code 3} in this buffer. * * @throws IndexOutOfBoundsException * if {@code this.readableBytes} is less than {@code 3} */ public abstract int readMediumLE(); /** * Gets an unsigned 24-bit medium integer at the current {@code readerIndex} * and increases the {@code readerIndex} by {@code 3} in this buffer. * * @throws IndexOutOfBoundsException * if {@code this.readableBytes} is less than {@code 3} */ public abstract int readUnsignedMedium(); /** * Gets an unsigned 24-bit medium integer at the current {@code readerIndex} * in the Little Endian Byte Order and increases the {@code readerIndex} * by {@code 3} in this buffer. * * @throws IndexOutOfBoundsException * if {@code this.readableBytes} is less than {@code 3} */ public abstract int readUnsignedMediumLE(); /** * Gets a 32-bit integer at the current {@code readerIndex} * and increases the {@code readerIndex} by {@code 4} in this buffer. * * @throws IndexOutOfBoundsException * if {@code this.readableBytes} is less than {@code 4} */ public abstract int readInt(); /** * Gets a 32-bit integer at the current {@code readerIndex} * in the Little Endian Byte Order and increases the {@code readerIndex} * by {@code 4} in this buffer. * * @throws IndexOutOfBoundsException * if {@code this.readableBytes} is less than {@code 4} */ public abstract int readIntLE(); /** * Gets an unsigned 32-bit integer at the current {@code readerIndex} * and increases the {@code readerIndex} by {@code 4} in this buffer. * * @throws IndexOutOfBoundsException * if {@code this.readableBytes} is less than {@code 4} */ public abstract long readUnsignedInt(); /** * Gets an unsigned 32-bit integer at the current {@code readerIndex} * in the Little Endian Byte Order and increases the {@code readerIndex} * by {@code 4} in this buffer. * * @throws IndexOutOfBoundsException * if {@code this.readableBytes} is less than {@code 4} */ public abstract long readUnsignedIntLE(); /** * Gets a 64-bit integer at the current {@code readerIndex} * and increases the {@code readerIndex} by {@code 8} in this buffer. * * @throws IndexOutOfBoundsException * if {@code this.readableBytes} is less than {@code 8} */ public abstract long readLong(); /** * Gets a 64-bit integer at the current {@code readerIndex} * in the Little Endian Byte Order and increases the {@code readerIndex} * by {@code 8} in this buffer. * * @throws IndexOutOfBoundsException * if {@code this.readableBytes} is less than {@code 8} */ public abstract long readLongLE(); /** * Gets a 2-byte UTF-16 character at the current {@code readerIndex} * and increases the {@code readerIndex} by {@code 2} in this buffer. * * @throws IndexOutOfBoundsException * if {@code this.readableBytes} is less than {@code 2} */ public abstract char readChar(); /** * Gets a 32-bit floating point number at the current {@code readerIndex} * and increases the {@code readerIndex} by {@code 4} in this buffer. * * @throws IndexOutOfBoundsException * if {@code this.readableBytes} is less than {@code 4} */ public abstract float readFloat(); /** * Gets a 64-bit floating point number at the current {@code readerIndex} * and increases the {@code readerIndex} by {@code 8} in this buffer. * * @throws IndexOutOfBoundsException * if {@code this.readableBytes} is less than {@code 8} */ public abstract double readDouble();
下面是一些write*原始类型的方法,会增加写索引
/** * Sets the specified 16-bit short integer at the current * {@code writerIndex} and increases the {@code writerIndex} by {@code 2} * in this buffer. The 16 high-order bits of the specified value are ignored. * * @throws IndexOutOfBoundsException * if {@code this.writableBytes} is less than {@code 2} */ public abstract ByteBuf writeShort(int value); /** * Sets the specified 16-bit short integer in the Little Endian Byte * Order at the current {@code writerIndex} and increases the * {@code writerIndex} by {@code 2} in this buffer. * The 16 high-order bits of the specified value are ignored. * * @throws IndexOutOfBoundsException * if {@code this.writableBytes} is less than {@code 2} */ public abstract ByteBuf writeShortLE(int value); /** * Sets the specified 24-bit medium integer at the current * {@code writerIndex} and increases the {@code writerIndex} by {@code 3} * in this buffer. * * @throws IndexOutOfBoundsException * if {@code this.writableBytes} is less than {@code 3} */ public abstract ByteBuf writeMedium(int value); /** * Sets the specified 24-bit medium integer at the current * {@code writerIndex} in the Little Endian Byte Order and * increases the {@code writerIndex} by {@code 3} in this * buffer. * * @throws IndexOutOfBoundsException * if {@code this.writableBytes} is less than {@code 3} */ public abstract ByteBuf writeMediumLE(int value); /** * Sets the specified 32-bit integer at the current {@code writerIndex} * and increases the {@code writerIndex} by {@code 4} in this buffer. * * @throws IndexOutOfBoundsException * if {@code this.writableBytes} is less than {@code 4} */ public abstract ByteBuf writeInt(int value); /** * Sets the specified 32-bit integer at the current {@code writerIndex} * in the Little Endian Byte Order and increases the {@code writerIndex} * by {@code 4} in this buffer. * * @throws IndexOutOfBoundsException * if {@code this.writableBytes} is less than {@code 4} */ public abstract ByteBuf writeIntLE(int value); /** * Sets the specified 64-bit long integer at the current * {@code writerIndex} and increases the {@code writerIndex} by {@code 8} * in this buffer. * * @throws IndexOutOfBoundsException * if {@code this.writableBytes} is less than {@code 8} */ public abstract ByteBuf writeLong(long value); /** * Sets the specified 64-bit long integer at the current * {@code writerIndex} in the Little Endian Byte Order and * increases the {@code writerIndex} by {@code 8} * in this buffer. * * @throws IndexOutOfBoundsException * if {@code this.writableBytes} is less than {@code 8} */ public abstract ByteBuf writeLongLE(long value); /** * Sets the specified 2-byte UTF-16 character at the current * {@code writerIndex} and increases the {@code writerIndex} by {@code 2} * in this buffer. The 16 high-order bits of the specified value are ignored. * * @throws IndexOutOfBoundsException * if {@code this.writableBytes} is less than {@code 2} */ public abstract ByteBuf writeChar(int value); /** * Sets the specified 32-bit floating point number at the current * {@code writerIndex} and increases the {@code writerIndex} by {@code 4} * in this buffer. * * @throws IndexOutOfBoundsException * if {@code this.writableBytes} is less than {@code 4} */ public abstract ByteBuf writeFloat(float value); /** * Sets the specified 64-bit floating point number at the current * {@code writerIndex} and increases the {@code writerIndex} by {@code 8} * in this buffer. * * @throws IndexOutOfBoundsException * if {@code this.writableBytes} is less than {@code 8} */ public abstract ByteBuf writeDouble(double value);
下面是一些字节搜索定位方法:
/** * Locates the first occurrence of the specified {@code value} in this * buffer. The search takes place from the specified {@code fromIndex} * (inclusive) to the specified {@code toIndex} (exclusive). 查找在当buf的fromIndex(inclusive)和toIndex(exclusive),之间是否存在指定的字节, 找到返回对应的索引,否则返回-1 * <p> * If {@code fromIndex} is greater than {@code toIndex}, the search is * performed in a reversed order. 如果fromIndex大于toIndex,则反向执行搜索 * <p> * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. 此方法不会修改读写索引 * * @return the absolute index of the first occurrence if found. * {@code -1} otherwise. */ public abstract int indexOf(int fromIndex, int toIndex, byte value); /** * Locates the first occurrence of the specified {@code value} in this * buffer. The search takes place from the current {@code readerIndex} * (inclusive) to the current {@code writerIndex} (exclusive). * <p> 从当前buf的读索引开始,到写索引之间,搜索是否存在指定字节,存在则返回第一次发生的索引, 否则返回-1 * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. 此方法不会修改读写索引 * * @return the number of bytes between the current {@code readerIndex} * and the first occurrence if found. {@code -1} otherwise. */ public abstract int bytesBefore(byte value); /** * Locates the first occurrence of the specified {@code value} in this * buffer. The search starts from the current {@code readerIndex} * (inclusive) and lasts for the specified {@code length}. 与上面方法不同的是,不是到写索引,而是指定了搜索返回即[readerIndex,readerIndex+length) * <p> * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. *此方法不会修改读写索引 * @return the number of bytes between the current {@code readerIndex} * and the first occurrence if found. {@code -1} otherwise. * * @throws IndexOutOfBoundsException * if {@code length} is greater than {@code this.readableBytes} */ public abstract int bytesBefore(int length, byte value); /** * Locates the first occurrence of the specified {@code value} in this * buffer. The search starts from the specified {@code index} (inclusive) * and lasts for the specified {@code length}. 与上面方法不同的是,从指定的索引开始搜索 * <p> * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. *此方法不会修改读写索引 * @return the number of bytes between the specified {@code index} * and the first occurrence if found. {@code -1} otherwise. * * @throws IndexOutOfBoundsException * if {@code index + length} is greater than {@code this.capacity} */ public abstract int bytesBefore(int index, int length, byte value); 再来遍历buf,处理字节: /** * Iterates over the readable bytes of this buffer with the specified {@code processor} in ascending order. * 遍历buf,以升序ByteProcessor#process处理字节 * @return {@code -1} if the processor iterated to or beyond the end of the readable bytes. * The last-visited index If the {@link ByteProcessor#process(byte)} returned {@code false}. 如果迭代器超过可读索引位置,则返回-1,否则返回上次ByteProcessor#process(byte)方法,返回false的索引位置 */ public abstract int forEachByte(ByteProcessor processor); /** * Iterates over the specified area of this buffer with the specified {@code processor} in ascending order. * (i.e. {@code index}, {@code (index + 1)}, .. {@code (index + length - 1)}) *与上面的不同的多了开始索引,和范围控制length * @return {@code -1} if the processor iterated to or beyond the end of the specified area. * The last-visited index If the {@link ByteProcessor#process(byte)} returned {@code false}. */ public abstract int forEachByte(int index, int length, ByteProcessor processor); /** * Iterates over the readable bytes of this buffer with the specified {@code processor} in descending order. *降序方式ByteProcessor#process处理字节 * @return {@code -1} if the processor iterated to or beyond the beginning of the readable bytes. * The last-visited index If the {@link ByteProcessor#process(byte)} returned {@code false}. */ public abstract int forEachByteDesc(ByteProcessor processor); /** * Iterates over the specified area of this buffer with the specified {@code processor} in descending order. * (i.e. {@code (index + length - 1)}, {@code (index + length - 2)}, ... {@code index}) *与上面的不同的多了开始索引,和范围控制length * * @return {@code -1} if the processor iterated to or beyond the beginning of the specified area. * The last-visited index If the {@link ByteProcessor#process(byte)} returned {@code false}. */ public abstract int forEachByteDesc(int index, int length, ByteProcessor processor);
//ByteProcessor
package io.netty.util; /** * Provides a mechanism to iterate over a collection of bytes. */ public interface ByteProcessor { /** * A {@link ByteProcessor} which finds the first appearance of a specific byte. */ class IndexOfProcessor implements ByteProcessor { private final byte byteToFind; public IndexOfProcessor(byte byteToFind) { this.byteToFind = byteToFind; } @Override public boolean process(byte value) { return value != byteToFind; } } /** * A {@link ByteProcessor} which finds the first appearance which is not of a specific byte. */ class IndexNotOfProcessor implements ByteProcessor { private final byte byteToNotFind; public IndexNotOfProcessor(byte byteToNotFind) { this.byteToNotFind = byteToNotFind; } @Override public boolean process(byte value) { return value == byteToNotFind; } } /** * Aborts on a {@code NUL (0x00)}. */ ByteProcessor FIND_NUL = new IndexOfProcessor((byte) 0); /** * Aborts on a non-{@code NUL (0x00)}. */ ByteProcessor FIND_NON_NUL = new IndexNotOfProcessor((byte) 0); /** * Aborts on a {@code CR ('\r')}. */ ByteProcessor FIND_CR = new IndexOfProcessor((byte) '\r'); /** * Aborts on a non-{@code CR ('\r')}. */ ByteProcessor FIND_NON_CR = new IndexNotOfProcessor((byte) '\r'); /** * Aborts on a {@code LF ('\n')}. */ ByteProcessor FIND_LF = new IndexOfProcessor((byte) '\n'); /** * Aborts on a non-{@code LF ('\n')}. */ ByteProcessor FIND_NON_LF = new IndexNotOfProcessor((byte) '\n'); /** * Aborts on a {@code CR (';')}. */ ByteProcessor FIND_SEMI_COLON = new IndexOfProcessor((byte) ';'); /** * Aborts on a {@code CR ('\r')} or a {@code LF ('\n')}. */ ByteProcessor FIND_CRLF = new ByteProcessor() { @Override public boolean process(byte value) { return value != '\r' && value != '\n'; } }; /** * Aborts on a byte which is neither a {@code CR ('\r')} nor a {@code LF ('\n')}. */ ByteProcessor FIND_NON_CRLF = new ByteProcessor() { @Override public boolean process(byte value) { return value == '\r' || value == '\n'; } }; /** * Aborts on a linear whitespace (a ({@code ' '} or a {@code '\t'}). */ ByteProcessor FIND_LINEAR_WHITESPACE = new ByteProcessor() { @Override public boolean process(byte value) { return value != ' ' && value != '\t'; } }; /** * Aborts on a byte which is not a linear whitespace (neither {@code ' '} nor {@code '\t'}). */ ByteProcessor FIND_NON_LINEAR_WHITESPACE = new ByteProcessor() { @Override public boolean process(byte value) { return value == ' ' || value == '\t'; } }; /** * @return {@code true} if the processor wants to continue the loop and handle the next byte in the buffer. * {@code false} if the processor wants to stop handling bytes and abort the loop. */ boolean process(byte value) throws Exception; }
发表评论
-
netty NioSocketChannel解析
2017-09-29 12:50 1369netty 抽象BootStrap定义:http://dona ... -
netty Pooled字节buf分配器
2017-09-28 13:00 2099netty 字节buf定义:http://donald-dra ... -
netty Unpooled字节buf分配器
2017-09-26 22:01 2501netty 字节buf定义:http://donald-dra ... -
netty 抽象字节buf分配器
2017-09-26 08:43 1348netty 字节buf定义:http:// ... -
netty 复合buf概念
2017-09-25 22:31 1348netty 字节buf定义:http://donald-dra ... -
netty 抽象字节buf引用计数器
2017-09-22 12:48 1627netty 字节buf定义:http://donald-dra ... -
netty 抽象字节buf解析
2017-09-22 09:00 1877netty 通道接口定义:http://donald-drap ... -
netty 资源泄漏探测器
2017-09-21 09:37 1440netty 通道接口定义:http://donald-drap ... -
netty 默认通道配置后续
2017-09-18 08:36 2225netty 通道接口定义:http://donald-drap ... -
netty 默认通道配置初始化
2017-09-17 22:51 2070netty 通道接口定义:http://donald-drap ... -
netty 通道配置接口定义
2017-09-17 14:51 1119netty 通道接口定义:http://donald-drap ... -
netty NioServerSocketChannel解析
2017-09-16 13:01 1911netty ServerBootStrap解析:http:// ... -
netty 抽象nio消息通道
2017-09-15 15:30 1257netty 通道接口定义:http:/ ... -
netty 抽象nio字节通道
2017-09-14 22:39 1243netty 通道接口定义:http:/ ... -
netty 抽象nio通道解析
2017-09-14 17:23 992netty 通道接口定义:http://donald-drap ... -
netty 抽象通道后续
2017-09-13 22:40 1335netty Inboudn/Outbound通道Inv ... -
netty 通道Outbound缓冲区
2017-09-13 14:31 2221netty 通道接口定义:http:/ ... -
netty 抽象Unsafe定义
2017-09-12 21:24 1138netty 通道接口定义:http:/ ... -
netty 抽象通道初始化
2017-09-11 12:56 1897netty 管道线定义-ChannelPipeline:htt ... -
netty 通道接口定义
2017-09-10 15:36 1930netty Inboudn/Outbound通道Invoker ...
相关推荐
**字节序**定义了多字节数据在内存中的排列方式。有两种主要的字节序: - **Little-Endian**: 在这种格式下,低字节位于内存较低的位置,而高字节位于较高位置。例如,如果有一个整数`0x12345678`,在Little-Endian...
- 例如,在某些场景下,如果需要接收的数据量固定为 25 字节,而实际设置的是 50 字节,那么可以修改为只接收 25 字节。 - 此外,还需要注意操作系统当前的设置,确保与 LoadRunner 的配置相匹配。 #### 二、设置...
在 Java 中,将对象转换为 byte 数组是一种常见的操作,特别是在使用 Netty 进行通信协议传输的场景中。那么,如何方便地将一个 Java 对象构造成一个 byte 数组呢? 方法 1:使用 ByteBuf 在 Netty 中,我们可以...
包括:源程序工程文件、Proteus仿真工程文件、配套技术手册等 1、采用51/52单片机作为主控芯片; 2、采用1602液晶显示; 3、采用5*8矩阵键盘输入; 4、功能键包括:复位键(RST),回删键(DEL),确定键(OK),第二功能切换(2U),背光灯键(LED); 5、运算均为单精度浮点数,包括: 加(+),减(-),乘(x),除(÷), e底指数(e^n),N次方(x^n),开N次方(sqrt), 正弦(sin),余弦(cos),正切(tan), 对数(log), 阶乘(n!)(n<35), 排列(Arn), 累加(∑), *开启第二功能(2U)后可用: 反正弦(asin),反余弦(acos),反正切(atan), 组合(Crn)
内容概要:本文详细介绍了如何利用三菱FX2N系列PLC构建机械手控制系统。主要内容涵盖电路图设计、IO表配置、源程序编写以及单机组态。文中提供了具体的梯形图编程实例,展示了如何通过PLC精确控制机械手的各种动作,如抓取、移动和放置。此外,还分享了许多实用的调试技巧和注意事项,强调了传感器状态交叉验证和关键动作的时间守护机制。通过这些内容,读者可以全面了解PLC在机械手控制中的应用。 适合人群:从事工业自动化领域的工程师和技术人员,尤其是对PLC编程和机械手控制感兴趣的初学者和有一定经验的研发人员。 使用场景及目标:适用于需要设计和实施机械手控制系统的工业场合,帮助工程师掌握PLC编程技巧,提高机械手控制系统的稳定性和可靠性。 其他说明:文章不仅提供理论指导,还包括大量实战代码和调试经验,有助于读者快速上手并在实践中不断优化系统性能。
内容概要:本文档提供了用于生成具有时尚性感元素的美女跳舞图像的提示词指南。文档内容包括角色设定为擅长描绘时尚与超现实主义图片的创作者,背景设定强调女性形象,偏好展现性感漂亮女孩的镜头表达。目标在于根据用户指令创作三幅统一风格的图像,注重色彩搭配和高清效果,同时确保每张图片都具备半身像、真实感和电影效果的特点。文档还给出了具体的输出示例,详细描述了人物形象、服装搭配以及场景布置等要素,旨在为用户提供满意的图像生成服务。; 适合人群:对图像生成感兴趣,尤其是喜欢带有时尚性感元素的美女图像的用户。; 使用场景及目标:①根据用户提供的简单场景信息(如户外或室内)生成三幅不同场景但风格统一的赛博朋克风格美女跳舞图像;②确保生成的图像符合特定的要求,如半身像、真实感、电影效果、性感服装、特定灯光效果等;③通过询问用户对生成图像的满意度来保证服务质量。; 其他说明:文档明确了图像生成的工作流程,从接收用户指令到根据反馈调整生成内容,确保整个过程高效且满足用户需求。同时,文档还限制了生成图像的具体条件,如场景必须为赛博朋克风格、不能出现鞋子和其他人等,以保证图像的独特性和一致性。
题目描述 1.问题描述 一个正整数如果任何一个数位不大于右边相邻的数位,则称为一个数位递增的 数,例如1135是一个数位递增的数,而1024不是一个数位递增的数。 给定正整数n,请问在整数1至n中有多少个数位递增的数? 输入格式 输入的第一行包含一个整数n。 输出格式 输出一行包含一个整数,表示答案。 样例输入 30 样例输出
内容概要:本文详细介绍了基于非对称纳什谈判的多微网电能共享运行优化策略及其MATLAB代码实现。首先阐述了纳什谈判和合作博弈的基本理论,然后将多微网电能共享合作运行模型分解为微网联盟效益最大化和合作收益分配两个子问题。文中展示了如何通过交替方向乘子法(ADMM)进行分布式求解,确保各微网隐私安全。此外,还探讨了电转气(P2G)和碳捕集(CCS)设备的应用,以实现低碳调度。最后,通过具体代码示例解释了模型的构建、求解及优化过程。 适合人群:对电力系统优化、博弈论、MATLAB编程感兴趣的科研人员和技术开发者。 使用场景及目标:适用于希望深入了解多微网电能共享优化策略的研究者,旨在提高微网联盟的整体效益并实现公平合理的收益分配。同时,该策略有助于降低碳排放,提升系统的环境友好性和经济性。 其他说明:文章提供了详细的代码注释和调试技巧,帮助读者更好地理解和实现这一复杂的优化策略。
内容概要:本文详细介绍了如何利用MATLAB进行六轴机械臂的视觉控制系统仿真。首先,通过MATLAB的图像处理工具箱捕捉并处理实时视频流,使用HSV颜色空间进行颜色阈值处理,从而定位红色小球的位置。然后,借助Robotics Toolbox中的逆运动学模块,将摄像头获取的目标位置转换为机械臂的关节角度,确保机械臂能够精准地追踪目标。此外,还讨论了路径规划的方法,如使用五次多项式插值和平滑滤波器,使机械臂的动作更加流畅。文中强调了实际应用中可能遇到的问题及其解决方法,如奇异点处理、坐标系转换和机械臂的速度限制等。 适合人群:具有一定编程基础和技术背景的研究人员、工程师以及对机器人视觉控制感兴趣的开发者。 使用场景及目标:适用于希望在MATLAB环境中快速搭建和测试机械臂视觉控制系统的科研人员和工程师。主要目标是掌握从图像处理到机械臂控制的完整流程,理解各模块的工作原理,并能够在实际项目中应用。 其他说明:本文不仅提供了详细的代码示例,还分享了许多实用的经验和技巧,帮助读者更好地理解和优化仿真系统。同时提醒读者注意仿真与现实之间的差异,如摄像头延迟、机械臂传动误差等问题。
KUKA机器人相关文档
KUKA机器人相关文档
内容概要:本文详细介绍了三相变流器的模型预测控制(MPC)在Matlab/Simulink环境下的实现过程。首先,初始化程序设置了关键参数,如直流母线电压、开关频率和控制周期等,确保系统的稳定性和效率。接着,通过MPC_sfun.c实现了核心控制算法,采用状态空间模型进行滚动预测,提高了系统的动态响应能力。最后,利用out.m生成高质量的仿真结果图,展示了负载突变时的快速恢复特性,并提供了优化建议,如调整代价函数权重和引入软约束等。 适合人群:电力电子工程师、控制系统研究人员以及对MPC感兴趣的科研工作者。 使用场景及目标:适用于需要精确控制电压电流的场合,如电动汽车充电站、风力发电系统等。主要目标是提高系统的动态响应速度、降低总谐波失真(THD),并在性能和计算负担之间取得平衡。 其他说明:文中提到了一些实用技巧,如控制周期的选择、预测步长的优化、图形绘制的最佳实践等,有助于读者更好地理解和应用MPC控制策略。同时,强调了在实际应用中需要注意的问题,如避免过高开关频率导致器件损坏等。
网络炒作策划要点解析.ppt
内容概要:本文详细介绍了三菱Q03UDE PLC使用SFC(顺序功能图)编程方法在16轴伺服控制系统中的应用。文章首先概述了硬件配置,包括500个IO点、16轴伺服控制以及触摸屏的画面编程。接着深入探讨了SFC编程的具体实现方式,如将复杂的轴控制分解为独立的流程块,利用并行结构解决多轴同步问题,通过触摸屏实时监控和反馈SFC步状态,以及如何高效管理和复用输出点。此外,文章还讨论了SFC在状态管理和报警处理方面的优势,并提供了具体的代码示例来展示其实现细节。最后,作者分享了一些实用技巧和注意事项,强调了SFC编程相比传统梯形图的优势。 适合人群:从事工业自动化控制系统的工程师和技术人员,尤其是对三菱PLC和SFC编程感兴趣的读者。 使用场景及目标:适用于需要进行复杂多轴伺服控制项目的工程师,旨在提高调试效率、减少信号冲突、缩短新人培养周期,并提供一种更加直观和高效的编程方法。 其他说明:文中提到的实际项目经验有助于读者更好地理解和应用SFC编程技术,同时也提醒了一些常见的错误和陷阱,帮助读者避免不必要的麻烦。
内容概要:本文详细介绍了如何使用LabVIEW实现与三菱FX3U PLC的串口通讯,采用Modbus无协议通讯方式进行简单读写操作。主要内容包括PLC通讯参数配置、LabVIEW工程结构搭建、Modbus报文构造方法以及具体的读写数据模块实现。文中提供了详细的代码示例和注意事项,帮助读者快速理解和实践这一通讯过程。 适合人群:对工业自动化有一定兴趣的技术人员,尤其是熟悉LabVIEW和三菱PLC的工程师。 使用场景及目标:适用于需要将LabVIEW作为上位机与三菱FX3U PLC进行串口通讯的应用场合,如工业控制系统、实验教学等。主要目标是掌握Modbus协议的基础知识及其在LabVIEW中的具体实现。 其他说明:文章还提供了一些常见的错误排查方法和实用技巧,如CRC校验的处理、地址偏移量的注意事项等。此外,附带了完整的源码供读者下载和参考。
图像检索_基于零样本开集的草图图像检索系统实现_附项目源码+流程教程_优质项目实战
基于C语言写的电话簿程序
包括:源程序工程文件、Proteus仿真工程文件、配套技术手册等 1、采用51单片机作为主控芯片; 2、采用1602液晶显示检测电压值,范围0~20V; 3、采用ADC0808进行模数转换;
内容概要:本文介绍了一个专业的剧本杀创作作家AI。它能根据客户需求创作各种风格和难度的剧本杀剧本,并提供创作建议和修改意见。其目标是创造引人入胜、逻辑严密的剧本体验。它的工作流程包括接收理解剧本要求、创作剧本框架情节、设计角色背景线索任务剧情走向、提供修改完善建议、确保剧本可玩性和故事连贯性。它需保证剧本原创、符合道德法律标准并在规定时间内完成创作。它具备剧本创作技巧、角色构建理解、线索悬念编织、文学知识和创意思维、不同文化背景下剧本风格掌握以及剧本杀游戏机制和玩家心理熟悉等技能。; 适合人群:有剧本杀创作需求的人群,如剧本杀爱好者、创作者等。; 使用场景及目标:①为用户提供符合要求的剧本杀剧本创作服务;②帮助用户完善剧本杀剧本,提高剧本质量。; 阅读建议:此资源详细介绍了剧本杀创作作家AI的功能和服务流程,用户可以依据自身需求与该AI合作,明确表达自己的创作需求并配合其工作流程。
内容概要:本文详细介绍了如何利用Matlab进行静态图片的美颜和特效处理。首先通过Viola-Jones算法进行人脸定位,然后采用双边滤波对皮肤进行磨皮处理,在HSV色彩空间中调整亮度以达到美白效果,最后运用小波变换将星空图等特效融合到图片中。整个过程中涉及多个图像处理技术和算法,如Haar特征、双边滤波、HSV转换、小波变换等。 适合人群:对图像处理感兴趣的初学者以及有一定Matlab基础的研发人员。 使用场景及目标:适用于希望深入了解图像处理原理并掌握具体实现方法的学习者;目标是能够独立完成简单的图像美化任务,如人像磨皮、美白、特效添加等。 其他说明:文中提供了完整的代码示例,帮助读者更好地理解和实践相关技术。同时强调了参数选择的重要性,并给出了合理的建议范围。