ByteBuffer 主要有以下属性
capacity
容量大小,表示最多可存放Byte 的数量
position
操作指针,当下一次调用get或put 时就会从这里读取,换句话说,每put/get一次,position就会递增一次。
limit
表示缓存区里 "有效" 的元素长度,
比如 ByteBuffer的容量capacity设置为10,那么这个10个字节默认都为0(表示无数值)
而limit 的作用则表示10个字节里有多少个字节是有效的。
假如往buffer put进5个字节,则limit为5.
ByteBuffer 主要的方法
clear() -- 主要用于在准备写入数据之前调用
清除Buffer里面的数据,即将所有字节清零,limit设置为0,position设置为0
每次读满buffer,准备要读下一次之前应该要清零,要不因为buffer满了而导致不能继续读。
源码:
public final Buffer clear() {
position = 0;
limit = capacity;
mark = -1;
return this;
}
flip() -- 主要用于写(即调用put方法)完数据后准备读(即调用get方法)
用于记录当前position位置(修改limit来记录当前有效字节位置),并将position清0。
源码:
public final Buffer flip() {
limit = position;
position = 0;
mark = -1;
return this;
}
reset() -- 主要用于循环读取buffer的数据使用
将当前position指针移动到上次调用mark()方法进行记录的位置
例如广播同一条消息给不同的客户端
源码:
public final Buffer reset() {
int m = mark;
if (m < 0)
throw new InvalidMarkException();
position = m;
return this;
}
mark() -- 主要用于准备reset之前使用
记录当前position位置,等待下次reset时使用
源码:
public final Buffer mark() {
mark = position;
return this;
}
当往buffer里put 完一次数据以后,position 跟limit 都会同时递增,基本是同步,
假如put 了10个字节,position跟limit 从0 开始一直递增到10。
而position正如前面所述,用于get或put 的操作,如果在往buffer里put完以后,不进行对position设置而直接get 的话,那自然是读取不了数据的。
remaining()
查询当前还有多少 “有效” 的数据可用,即判断position与limit 之间的差值。
示例代码:
循环 读取 控制台的输入内容,并写入到socket中
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
ByteBuffer buffer = ByteBuffer.allocate(1024);
while (true) {
try {
String s = reader.readLine();
byte[] bytes = s.getBytes(utf8);
buffer.clear();//每次写入buffer之前都清空一下
buffer.put(bytes);
buffer.flip();//每次准备从buffer里读取数据之前,都要重置一下position指针
socketChannel.write(buffer);
} catch (IOException e) {
e.printStackTrace();
}
}
为了初步了解,这段代码只是简单演示基本用法,实际上还要考虑bytes比buffer要大的情况,修改成如下代码:
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
ByteBuffer buffer = ByteBuffer.allocate(1024);
while (true) {
try {
String s = reader.readLine();
byte[] bytes = s.getBytes(utf8);
buffer.clear();
for (int offset = 0; offset < bytes.length; offset++) {
buffer.put(bytes[offset]);
if (buffer.remaining() == 0) {
buffer.flip();
socketChannel.write(buffer);
buffer.clear();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}