ByteBufferUtils
这是一个专为 java.nio.ByteBuffer
设计的工具类,旨在简化和扩展 ByteBuffer
的常用操作。ByteBuffer
是 Java NIO 的核心组件,用于高效的 I/O 操作,但其原生 API 在某些场景下使用起来较为繁琐,例如处理特定格式的数据(如按行读取)、复制、拆分等。ByteBufferUtils
封装了这些复杂操作,提供了更易于使用的静态方法。
设计理念
- 静态工具类: 所有方法都是静态的,无需实例化,方便直接调用。
- 副作用明确:
- 读取 (read) / 写入 (write) 方法: 通常会改变
ByteBuffer
的position
指针,因为它们消耗或填充了数据。 - 复制 (copy) / 搜索 (indexOf/lineEnd) 方法: 通常被设计为无副作用的,它们在内部操作前会保存
position
和limit
,操作后会恢复,不影响调用者后续对缓冲区的操作。
- 读取 (read) / 写入 (write) 方法: 通常会改变
- 健壮性: 关键方法(如
readLine
)包含了最大长度检查(maxlength
),可以抛出LengthOverflowException
,防止恶意或错误的数据包耗尽服务器内存。 - 协议友好: 提供了处理网络协议中常见数据格式(行、定长字符串、不同字节序的整数)的专用方法,极大地简化了网络编程中的编解码逻辑。
方法详解
缓冲区操作 (Buffer Manipulation)
composite(ByteBuffer byteBuffer1, ByteBuffer byteBuffer2)
- 功能: 将两个
ByteBuffer
的可读内容(从position
到limit
)合并成一个新的ByteBuffer
。 - 参数:
byteBuffer1
: 第一个源缓冲区。byteBuffer2
: 第二个源缓冲区。
- 返回: 一个新的
ByteBuffer
,其内容是byteBuffer1
和byteBuffer2
可读部分的顺序拼接。新缓冲区的position
为 0,limit
为其容量。 - 场景: 当一个逻辑上的数据包被网络拆分成两个物理包时,可以用此方法将其拼接成一个完整的包进行处理。
copy(ByteBuffer src, int srcStartindex, ByteBuffer dest, int destStartIndex, int length)
- 功能: 类似于
System.arraycopy
,将源ByteBuffer
底层数组的一部分字节复制到目标ByteBuffer
的底层数组中。 - 注意: 这是一个低级操作,直接操作底层数组,需要确保两个
ByteBuffer
都是由数组支持的(非 DirectByteBuffer)。
copy(ByteBuffer src, int startindex, int endindex)
- 功能: 复制源
ByteBuffer
中指定索引范围([startindex, endindex)
)的内容到一个新的ByteBuffer
中。 - 副作用: 无。此方法不改变源
ByteBuffer
的position
和limit
。 - 返回: 一个新的、包含了复制内容且已
flip()
的ByteBuffer
。
copy(ByteBuffer src)
- 功能: 复制源
ByteBuffer
的所有可读内容(从position
到limit
)到一个新的ByteBuffer
中。 - 副作用: 无。
- 返回: 一个新的、包含了复制内容且已
flip()
的ByteBuffer
。
split(ByteBuffer src, int unitSize)
- 功能: 将一个
ByteBuffer
按照指定的单元大小(unitSize
)拆分成一个ByteBuffer
数组。 - 返回:
- 如果
unitSize
大于或等于src
的limit
,说明不需要拆分,返回null
。 - 否则,返回一个
ByteBuffer
数组,其中每个元素都是一个分块,最后一个元素的大小可能是不足unitSize
的剩余部分。
- 如果
- 场景: 当需要将一个大文件或大数据块分片发送时非常有用。
数据读取 (Data Reading)
readBytes(ByteBuffer buffer, int length)
- 功能: 从
buffer
的当前position
读取指定length
的字节。 - 副作用: 有。
buffer
的position
会向前移动length
。 - 返回: 一个包含所读取字节的
byte[]
数组。
readString(ByteBuffer buffer, int length, String charset)
- 功能: 从
buffer
读取指定length
的字节,并使用指定的charset
解码成字符串。 - 副作用: 有。
buffer
的position
会向前移动length
。 - 返回: 解码后的字符串。
readLine(ByteBuffer buffer, String charset, Integer maxlength)
- 功能: 核心方法之一。从
buffer
的当前position
开始,查找行分隔符(\n
或\r\n
),并读取这一行的数据作为字符串返回。 - 副作用: 有。
buffer
的position
会移动到行分隔符之后,为下一次读取做准备。 - 参数:
maxlength
: 允许读取的最大行长度,用于防止因数据格式错误或恶意攻击导致的内存溢出。
- 返回:
- 如果找到一个完整的行,则返回该行内容的字符串(不包含
\r\n
)。 - 如果缓冲区中没有完整的行(即没有找到行分隔符),则返回
null
,表示需要等待更多数据。
- 如果找到一个完整的行,则返回该行内容的字符串(不包含
- 场景: 处理基于文本行的协议,如 HTTP, SMTP, POP3, FTP 等。
readLine(ByteBuffer buffer, String charset)
- 功能:
readLine
的便捷版本,内部调用readLine(buffer, charset, Integer.MAX_VALUE)
,即不限制最大行长度。
readString(ByteBuffer buffer, String charset, char endChar, Integer maxlength)
- 功能: 从
buffer
读取字符串,直到遇到指定的结束字符endChar
为止。 - 副作用: 有。
buffer
的position
会移动到endChar
之后。 - 返回:
- 如果找到
endChar
,返回从开始到endChar
之前的内容字符串。 - 如果未找到,返回
null
。
- 如果找到
read(ByteBuffer buffer)
/ readShort(ByteBuffer buffer)
- 功能: 分别从
buffer
读取一个byte
或一个short
。 - 副作用: 有。
position
会相应移动 1 或 2 个字节。
readUB1(ByteBuffer buffer)
/ readUB2(ByteBuffer buffer)
/ readUB4(ByteBuffer buffer)
- 功能: 读取 1、2 或 4 个字节,并将其解析为无符号整数(Unsigned Byte)。由于 Java 没有原生无符号类型,结果会存放在更大的数据类型中(如
int
或long
)。此系列方法按小端字节序 (Little-Endian) 读取。 - 副作用: 有。
readUB2WithBigEdian(ByteBuffer buffer)
/ readUB4WithBigEdian(ByteBuffer buffer)
- 功能: 同上,但按大端字节序 (Big-Endian) 读取。网络协议(如 TCP/IP)的标准字节序就是大端。
- 副作用: 有。
数据写入 (Data Writing)
writeUB2(ByteBuffer buffer, int i)
/ writeUB4(ByteBuffer buffer, long l)
- 功能: 将一个整数
i
或长整数l
的低 2 或 4 个字节按小端字节序写入buffer
。 - 副作用: 有。
buffer
的position
会相应移动 2 或 4 个字节。
writeUB2WithBigEdian(ByteBuffer buffer, int i)
/ writeUB4WithBigEdian(ByteBuffer buffer, long l)
- 功能: 同上,但按大端字节序写入。
- 副作用: 有。
搜索与定位 (Searching & Positioning)
lineEnd(ByteBuffer buffer, int maxlength)
- 功能: 在
buffer
中从当前position
开始查找行结束符(\n
或\r\n
)的位置。 - 副作用: 有。为了查找,此方法会临时移动
position
,但在找到或未找到后,会恢复position
到调用前的状态。因此,对调用者来说,可以视为无副作用。 - 返回:
- 如果找到,返回行内容结束的索引(即
\r
或\n
的位置)。 - 如果未找到,返回 -1。
- 如果找到,返回行内容结束的索引(即
- 注意: 这是
readLine
的底层实现。
indexOf(ByteBuffer buffer, char theChar, int maxlength)
- 功能: 在
buffer
中从当前position
开始查找指定字符theChar
首次出现的位置。 - 副作用: 有,同
lineEnd
,对调用者可视为无副作用。 - 返回:
- 如果找到,返回该字符的绝对索引。
- 如果未找到,返回 -1。
编码转换 (Encoding)
getUtf8(byte[] bytes)
- 功能: 一个将
byte[]
数组转换为 UTF-8 编码字符串的便捷方法。 - 返回: UTF-8 字符串。