Java Nio 简明教程

Java NIO - Buffer

Java NIO 中的缓冲区可以看作一个简单的对象,它充当定大小数据块的容器,可用于向通道写入数据或从通道读取数据,以便缓冲区充当通道的端点。

它提供了成套的方法,以便于处理内存块以将数据读入通道或从通道写入数据。

与经典 IO 相比,缓冲区使得 NIO 包更有效率且更快速,因为在 IO 的情况下,数据是以流的形式处理的,不支持异步和并发的数据流。此外,IO 也不允许以块或字节组的形式执行数据。

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

  1. ` Capacity ` − 可以存储在缓冲区中的数据/字节的最大数量。不能更改缓冲区的容量。缓冲区已满后,在向其中写入数据之前应将其清除。

  2. Limit − 限制有意义,具体取决于缓冲区的模式,即在缓冲区的写入模式中,限制等于容量,这意味着可以在缓冲区中写入的最大数据量。而在缓冲区的读取模式中,限制意味着可以从缓冲区中读取的数据量。

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

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

Buffer Type

Java NIO 缓冲区可以根据缓冲区处理的数据类型进行以下分类:

  1. ByteBuffer

  2. MappedByteBuffer

  3. CharBuffer

  4. DoubleBuffer

  5. FloatBuffer

  6. IntBuffer

  7. LongBuffer

  8. ShortBuffer

Important methods of Buffer

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

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

  2. read() and put() − 通道的 read 方法用于将数据从通道写入缓冲区,而 put 是缓冲区的一种方法,用于将数据写入缓冲区。

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

  4. write() and get() − 通道的 write 方法用于将数据从缓冲区写入通道,而 get 是缓冲区的一种方法,用于从缓冲区读取数据。

  5. rewind() − 当需要重新读取时,使用 rewind 方法,因为它将位置设置回 0,并且不会更改限制的值。

  6. clear() and compact() − clear 和 compact 这两种方法都用于使缓冲区从读取模式变为写入模式。 clear() 方法将位置变为 0,并将限制变为容量,在这个方法中,缓冲区中的数据不会被清除,只有标记会被重新初始化。另一方面, compact() 方法在仍然有未读取的数据并且我们仍然使用缓冲区的写入模式的情况下使用,在这种情况下,compact 方法将所有未读取的数据复制到缓冲区的开头,并将位置设置到最后一个未读元素的后面。限制属性仍然设置为 capacity。

  7. mark() and reset() − 如名称所示,mark 方法用于标记缓冲区中的任何特定位置,而 reset 使位置回到标记的位置。

Example

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

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());
   }
}

Output

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