ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
### 缓冲区细节 缓冲区由数据和四个索引组成,以有效地访问和操作该数据:mark、position、limit 和 capacity(标记、位置、限制和容量)。伴随着的还有一组方法可以设置和重置这些索引,并可查询它们的值。 | | | | :----- | :----- | | **capacity()** | 返回缓冲区的 capacity | |**clear()** |清除缓冲区,将 position 设置为零并 设 limit 为 capacity;可调用此方法来覆盖现有缓冲区| |**flip()** | 将 limit 设置为 position,并将 position 设置为 0;此方法用于准备缓冲区,以便在数据写入缓冲区后进行读取| |**limit()** |返回 limit 的值| |**limit(int limit)**| 重设 limit| |**mark()** |设置 mark 为当前的 position | |**position()** |返回 position | |**position(int pos)**| 设置 position| |**remaining()** |返回 limit 到 position | |**hasRemaining()**| 如果在 position 与 limit 中间有元素,返回 `true`| 从缓冲区插入和提取数据的方法通过更新索引来反映所做的更改。下例使用一种非常简单的算法(交换相邻字符)来对 **CharBuffer** 中的字符进行加扰和解扰。代码示例: ```java // newio/UsingBuffers.java // (c)2017 MindView LLC: see Copyright.txt // 我们无法保证该代码是否适用于其他用途。 // 访问 http://OnJava8.com 了解更多本书信息。 import java.nio.*; public class UsingBuffers { private static void symmetricScramble(CharBuffer buffer) { while(buffer.hasRemaining()) { buffer.mark(); char c1 = buffer.get(); char c2 = buffer.get(); buffer.reset(); buffer.put(c2).put(c1); } } public static void main(String[] args) { char[] data = "UsingBuffers".toCharArray(); ByteBuffer bb = ByteBuffer.allocate(data.length * 2); CharBuffer cb = bb.asCharBuffer(); cb.put(data); System.out.println(cb.rewind()); symmetricScramble(cb); System.out.println(cb.rewind()); symmetricScramble(cb); System.out.println(cb.rewind()); } } ``` 输出结果: ``` UsingBuffers sUniBgfuefsr UsingBuffers ``` 虽然可以通过使用 **char** 数组调用 `wrap()` 直接生成 **CharBuffer**,但是底层的 **ByteBuffer** 将被分配,而 **CharBuffer** 将作为 **ByteBuffer** 上的视图生成。这强调了目标始终是操作 **ByteBuffer**,因为它与通道交互。 下面是程序在 `symmetricgrab()` 方法入口时缓冲区的样子: ![1554546627710](../images/1554546627710.png) position 指向缓冲区中的第一个元素,capacity 和 limit 紧接在最后一个元素之后。在`symmetricgrab()` 中,**while** 循环迭代到 position 等于 limit。当在缓冲区上调用相对位置的 `get()` 或 `put()` 函数时,缓冲区的位置会发生变化。你可以调用绝对位置的 `get()` 和 `put()` 方法,它们包含索引参数:`get()` 或 `put()` 发生的位置。这些方法不修改缓冲区 position 的值。 当控件进入 **while** 循环时,使用 `mark()` 设置 mark 的值。缓冲区的状态为: ![1554546666685](../images/1554546666685.png) 两个相对 `get()` 调用将前两个字符的值保存在变量 `c1` 和 `c2` 中。在这两个调用之后,缓冲区看起来是这样的: ![1554546693664](../images/1554546693664.png) 为了执行交换,我们在位置 0 处编写 `c2`,在位置 1 处编写 `c1`。我们可以使用绝对 `put()` 方法来实现这一点,或者用 `reset()` 方法,将 position 的值设置为 mark: ![1554546847181](../images/1554546847181.png) 两个 `put()` 方法分别编写 `c2` 和 `c1` : ![1554546861836](../images/1554546861836.png) 在下一次循环中,将 mark 设置为 position 的当前值: ![1554546881189](../images/1554546881189.png) 该过程将继续,直到遍历整个缓冲区为止。在 **while** 循环的末尾,position 位于缓冲区的末尾。如果显示缓冲区,则只显示位置和限制之间的字符。因此,要显示缓冲区的全部内容,必须使用 `rewind()` 将 position 设置为缓冲区的开始位置。这是 `rewind()` 调用后缓冲区的状态(mark 的值变成未定义): ![1554546890132](../images/1554546890132.png) 再次调用 `symmetricgrab()` 方法时,**CharBuffer** 将经历相同的过程并恢复到原始状态。