Java中的ByteBuffer类是NIO包中用于处理字节数据的重要类,它提供了多种方法来读取、写入和操作字节数据。以下是ByteBuffer中一些常用方法的含义:
分配缓冲区:
ByteBuffer.allocate(int capacity):分配一个新的字节缓冲区,容量为capacity,使用Java堆内存。ByteBuffer.allocateDirect(int capacity):分配一个直接字节缓冲区,容量为capacity,使用直接内存(操作系统内存),适合长时间存储或与I/O操作相关的场景。
写入数据:
put(byte b):向当前位置写入一个字节,然后位置递增。put(byte[] src):将源数组中的所有字节写入缓冲区,当前位置递增。put(byte[] src, int offset, int length):将源数组中的指定范围的字节写入缓冲区。put(ByteBuffer src):将源缓冲区中的剩余字节写入此缓冲区。
读取数据:
get():从当前位置读取一个字节,然后位置递增。get(byte[] dst):从缓冲区读取字节到目标数组,读取的长度为数组长度。get(byte[] dst, int offset, int length):从缓冲区读取指定长度的字节到目标数组的指定位置。
位置和限制操作:
position():返回当前位置。position(int newPosition):设置当前位置。如果newPosition为负数或大于限制,则抛出异常。limit():返回限制位置(即第一个不应读取或写入的元素的索引)。limit(int newLimit):设置限制位置。如果newLimit为负数或大于容量,则抛出异常。capacity():返回缓冲区的容量(创建时指定,不可变)。
翻转和清除:
flip():将缓冲区从写入模式切换到读取模式。将限制设置为当前位置,然后将位置设置为0。clear():将缓冲区从读取模式切换到写入模式。将位置设置为0,将限制设置为容量,但不清除数据(只是重置标记,以便重新写入)。rewind():将位置设置为0,限制保持不变,用于重新读取数据。
标记和重置:
mark():在当前位置设置标记,以便后续通过reset()返回。reset():将位置重置为之前标记的位置。
剩余空间:
remaining():返回当前位置与限制之间的元素数量(即剩余可读或可写的字节数)。hasRemaining():告知在当前位置和限制之间是否有元素。
压缩操作:
compact():将缓冲区中从当前位置到限制之间的字节复制到缓冲区的开头,然后将位置设置为复制的字节数,限制设置为容量。这用于在读取部分数据后,准备继续写入数据,并保留未读取的数据。
切片和复制:
slice():创建一个新的字节缓冲区,其内容共享原缓冲区的内容,但有自己的位置、限制和标记。新缓冲区的内容从原缓冲区的当前位置开始。duplicate():创建一个新的字节缓冲区,共享原缓冲区的内容,且拥有独立的position、limit和mark。
字节顺序:
order(ByteOrder bo):设置或获取字节顺序(大端或小端)。
其他:
array():返回缓冲区的字节数组(仅当缓冲区是非直接缓冲区且可访问时)。isDirect():判断缓冲区是否为直接缓冲区。
在您提供的代码中,我们使用了以下ByteBuffer方法:
remaining():获取剩余可读字节数。mark():标记当前位置。getInt():从当前位置读取一个int(4字节),然后位置递增4。get(byte[] dst):从缓冲区读取字节到指定数组。reset():将位置重置到最近一次标记的位置。flip():将缓冲区从写入模式切换到读取模式。compact():压缩缓冲区,将未读数据移到缓冲区开头,以便后续写入。slice():创建一个共享原缓冲区内容的新缓冲区,用于处理剩余数据。
在优化后的代码中,我们使用了这些方法来处理粘包和拆包问题,并管理会话缓冲区。
有几个值的概念
1、position:当前指针的位置
2、limit:当前会话缓冲区 的存放内容大小
3、capacity:当前会话缓冲区 最大的容量,启动的时候可以配置大小
1、下图:position=0,limit=18,capacity=5121
指针正在位置0,会话缓冲区有18个字节,会话缓冲区最大容量是5121字节

2、下图:position=4,limit=18,capacity=5121
屌用了getInt,读取了前4字节,position移动到了第4的位置
