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

缓冲区的重要方法

如前所述,缓冲区充当内存对象,它提供了一组方法,使处理内存块更加方便。以下是缓冲区的重要方法:

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

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

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

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

  • rewind() - 当需要重新读取时使用 rewind 方法,因为它将位置重置为零,并且不更改限制的值。

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

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

  • mark() 和 reset() - 顾名思义,mark 方法用于在缓冲区中标记任何特定位置,而 reset 将位置恢复到标记的位置。

示例

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

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

public class BufferDemo {
   public static void main (String [] args) {
      //allocate a character type buffer.
      CharBuffer buffer = CharBuffer.allocate(10);
      String text = "bufferDemo";
      System.out.println("Input text: " + text);
      for (int i = 0; i < text.length(); i++) {
         char c = text.charAt(i);
         //put character in buffer.
		 buffer.put(c);
      }
      int buffPos = buffer.position();
      System.out.println("Position after data is written into buffer: " + buffPos);
      buffer.flip();
      System.out.println("Reading buffer contents:");
      while (buffer.hasRemaining()) {
         System.out.println(buffer.get());                   
      }
      //set the position of buffer to 5.
      buffer.position(5);
      //sets this buffer's mark at its position
      buffer.mark();
      //try to change the position
      buffer.position(6);
      //calling reset method to restore to the position we marked.
      //reset() raise InvalidMarkException if either the new position is less
      //than the position marked or merk has not been setted.
      buffer.reset();
      System.out.println("Restored buffer position : " + 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
广告