Java NIO - 缓冲区

Java NIO 中的缓冲区可以视为一个简单的对象,充当数据块的固定大小容器,可用于将数据写入通道或从通道读取数据,因此缓冲区充当通道的端点。

它提供了一组方法,可以更方便地处理内存块,以便从通道读取和写入数据。

与传统 IO 相比,缓冲区使 NIO 包更高效、更快速,因为 IO 数据以流的形式处理,不支持异步和并发数据流。此外,IO 不允许以块或字节组的形式执行数据。

定义 Java NIO 缓冲区的主要参数可以定义为 −

  • 容量 −缓冲区中可以存储的最大数据量/字节数。缓冲区的容量不能改变。一旦缓冲区已满,应在写入之前清除它。

  • 限制 − 限制具有缓冲区模式的含义,即在缓冲区的写入模式下,限制等于容量,这意味着可以写入缓冲区的最大数据量。而在缓冲区的读取模式下,限制意味着可以从缓冲区读取多少数据的限制。

  • 位置 − 指向缓冲区中光标的当前位置。在创建缓冲区时最初设置为 0,或者换句话说,它是下一个要读取或写入的元素的索引,通过 get() 和 put() 方法自动更新。

  • 标记 −在缓冲区中标记位置的书签。调用 mark() 方法时,将记录当前位置,调用 reset() 时,将恢复标记位置。

缓冲区类型

Java NIO 缓冲区可以根据缓冲区处理的数据类型分为以下几种 −

  • ByteBuffer
  • MappedByteBuffer
  • CharBuffer
  • DoubleBuffer
  • FloatBuffer
  • IntBuffer
  • LongBuffer
  • ShortBuffer

Buffer 的重要方法

如前所述,Buffer 充当内存对象,提供一组方法,使处理内存块更加方便。以下是 Buffer 的重要方法 −

  • allocate(int capacity) − 此方法用于分配一个以容量为参数的新缓冲区。如果传递的容量为负整数,Allocate 方法将抛出 IllegalArgumentException。

  • read() 和 put() − 通道的 read 方法用于将数据从通道写入缓冲区,而缓冲区的 put 方法用于将数据写入缓冲区。

  • flip() − flip 方法将缓冲区的模式从写入模式切换到读取模式。它还将位置设置回 0,并将限制设置为写入时位置的位置。

  • write() 和 get() −通道的 write 方法用于将数据从缓冲区写入通道,而 get 是缓冲区的方法,用于从缓冲区读取数据。

  • rewind() − 当需要重新读取时使用 rewind 方法,因为它将位置设置回零并且不会改变 limit 的值。

  • clear() 和 compact() − clear 和 compact 两种方法均用于将缓冲区从读取模式转换为写入模式。clear() 方法将位置设置为零,并将限制设置为容量,在此方法中,缓冲区中的数据不会被清除,只有标记会被重新初始化。

    另一方面,当仍有一些未读取的数据且我们仍然使用缓冲区的写入模式时,使用 compact() 方法,在这种情况下, compact 方法将所有未读数据复制到缓冲区的开头,并将位置设置为最后一个未读元素之后。限制属性仍设置为容量。

  • mark() 和 reset() − 顾名思义,mark 方法用于标记缓冲区中的任何特定位置,而 reset 使位置回到标记位置。

示例

以下示例显示了上述定义方法的实现。

import java.nio.ByteBuffer;
import java.nio.CharBuffer;

public class BufferDemo {
   public static void main (String [] args) {
        //分配一个字符类型缓冲区。
        CharBuffer buffer = CharBuffer.allocate(10);
        String text = "bufferDemo";
        System.out.println("输入文本:" + text);
        for (int i = 0; i < text.length(); i++) {
            char c = text.charAt(i);
            //将字符放入缓冲区。
            buffer.put(c);
        }
        int buffPos = buffer.position();
        System.out.println("数据写入缓冲区后的位置:" + buffPos);
        buffer.flip();
        System.out.println("正在读取缓冲区内容:");
        while (buffer.hasRemaining()) {
        System.out.println(buffer.get());
        }
        //将缓冲区的位置设置为 5。
        buffer.position(5);
        //将此缓冲区的标记设置为其位置
        buffer.mark();
        //尝试改变位置
        buffer.position(6);
        //调用reset方法恢复到我们标记的位置。
        //如果新位置小于
        //标记的位置或标记尚未设置,reset()将引发InvalidMarkException。
        buffer.reset();
        System.out.println("恢复的缓冲区位置:"+buffer.position());
   }
}

输出

Input text: bufferDemo
Position after data is written into buffer: 10
Reading buffer contents:
b
u
f
f
e
r
D
e
m
o
Restored buffer position : 5