已转移
Java NIO 的前生今世 之三 NIO Buffer 详解
https://segmentfault.com/a/1190000006824155
Buffer 有三个属性:
-
capacity
-
position
-
limit
capacity是分配时确定的,是一个常量;position 和 limit 的含义与 Buffer 处于读模式或写模式有关,
写模式时,position是当前已写到的位置,limit是最大可写到的位置
读模式时,position是当前已读到的位置,limit是最大可读到的位置
limit - position 表示此时还可以写入/读取多少单位的数据,如果继续读或写就会报错。
写入数据到 Buffer
int bytesRead = inChannel.read(buf); //from channel write into buffer.
buf.put(127);
从 Buffer 中读取数据
int bytesWritten = inChannel.write(buf);
//read from buffer into channel.
byte aByte = buf.get();
重置 position
Buffer.rewind()方法可以重置 position 的值为0, 因此我们可以重新读取/写入 Buffer 了。
rewind() 主要针对于读模式. 在读模式时, 读取到 limit 后, 可以调用 rewind() 方法, 将读 position 置为0
关于 mark()和 reset()
我们可以通过调用 Buffer.mark()将当前的 position 的值保存起来, 随后可以通过调用 Buffer.reset()方法将 position 的值回复回来.
flip, rewind 和 clear 的区别
flip
flip 方法源码
public final Buffer flip() {
limit = position;
position = 0;
mark = -1;
return this;
}
Buffer 的读/写模式共用一个 position 和 limit 变量.
当从写模式变为读模式时, 原先的 写 position 就变成了读模式的 limit.
rewind
rewind 方法源码
public final Buffer rewind() {
position = 0;
mark = -1;
return this;
}
rewind, 即倒带, 这个方法仅仅是将 position 置为0.
clear
clear 方法源码:
public final Buffer clear() {
position = 0;
limit = capacity;
mark = -1;
return this;
}
根据源码我们可以知道, clear 将 positin 设置为0, 将 limit 设置为 capacity.
clear 方法使用场景:
-
在一个已经写满数据的 buffer 中, 调用 clear, 可以从头读取 buffer 的数据.
-
为了将一个 buffer 填充满数据, 可以调用 clear, 然后一直写入, 直到达到 limit.
读或写模式实际上也是改变pos、lim的值,上面的几个方法都是改变参数的值,对buf中的数据不会有影响,每次都会将mark重置为-1。
mark <= position <= limit <= capacity ,满足这个不等式,运行时才可以不报错。
Buffer 的比较
我们可以通过 equals() 或 compareTo() 方法比较两个 Buffer, 当且仅当如下条件满足时, 两个 Buffer 是相等的:
-
两个 Buffer 是相同类型的
-
两个 Buffer 的剩余的数据个数是相同的
-
两个 Buffer 的剩余的数据都是相同的.
通过上述条件我们可以发现, 比较两个 Buffer 时, 并不是 Buffer 中的每个元素都进行比较, 而是比较 Buffer 中剩余的元素.