Java NIO 中的 Buffer 缓冲区详解(上)

简介: Java NIO 中的 Buffer 缓冲区详解

Buffer 简介


Java NIO 中的 Buffer 用于和 NIO 通道进行交互。数据是通道读取到缓冲区,从缓冲区写入到通道中的。


image.png


缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存。这块内存被包装 NIO Buffer 对象,并且提供了一组方法,用来方便的访问这块内存。缓冲区世纪上一个容器对象,更直接的说,其实就是一个数组,在 NIO 库中,所有数据都是用缓冲区处理的。 在读取数据时,它直接读到缓冲区中;在写数据时,它也是写入到缓冲区中的;任何时候访问 NIO 中的数据,都是将它放到缓冲区中。而在面向流 I/O 系统中,所有数据都是直接写入或者直接将数据读取到 Stream 对象中。


在 NIO 中,所有的缓冲区类型都是继承于抽象类 Buffer, 最常用的就是 ByteBuffer. 对于 Java 中国呢的基本类型,金额都有一个具体 Buffer 类型与之对应,他们之间的继承关系如下图所示:


image.png


Buffer 的基本方法


1、使用 Buffer 读写数据,一般遵循以下四个步骤:


(1)写数据到 Buffer


(2)调用flip() 方法


(3)从 Buffer 中读取数据


(4)调用 clear() 方法或者 compact() 方法


当向 buffer 写数据时,buffer 会记录下写了多少数据。一旦要读数据,需要通过 flip() 方法将 buffer 从写模式切换到读模式。在读模式下,可以读取到之前写入到 buffer 的所有数据。一旦读完了所有的数据,就需要清空缓冲区,让它可以再次被写入。有两种方式能清空缓冲区:调用 clear() 或者 compact() 方法。clear() 方法会清空整个缓冲区。compact() 方法只会清除已经度过的数据。任何未读取的数据都被移动到了缓冲区的起始处,新写的数据将放到缓冲区未读数据的后面。


2、使用 Buffer 的例子


@Test
public void buffer01() throws IOException {
    // FileChannel
    String pathName = "/Users/zhengsh/sourcecode.io/zhengsh-vvip/nio/src/main/resources/01.txt";
    RandomAccessFile accessFile =
        new RandomAccessFile(pathName, "rw");
    FileChannel channel = accessFile.getChannel();
    // 创建 buffer , 大小
    ByteBuffer buffer = ByteBuffer.allocate(1024);
    // 读
    int bytesRead = channel.read(buffer);
    while (bytesRead != -1) {
        // read 模式
        buffer.flip();
        while (buffer.hasRemaining()) {
            System.out.println((char) buffer.get());
        }
        buffer.clear();
        channel.read(buffer);
    }
    accessFile.close();
}
@Test
public void buffer02() {
    // 创建 buffer
    IntBuffer buffer = IntBuffer.allocate(8);
    for (int i = 0; i < buffer.capacity(); i++) {
        int j = 2 * (i + 1);
        buffer.put(j);
    }
    // 重置缓冲区
    buffer.flip();
    while (buffer.hasRemaining()) {
        int value = buffer.get();
        System.out.println(value + "  ");
    }
}


Buffer 的 capactity、posittion 和limit


为了理解 Buffer 的工作原理,需要熟悉它的三个属性:


  • capacity


  • ponstition


  • limit


position 和 limit 的含义取决于 Buffer 处在读模式还是写模式。不管 buffer 处于什么模式,capactity 的含义总是一样的。


这里有一个关于 capacity, postition 和 limit 在读模式中的说明:


image.png


(1) capactiy


作为一个内存块,Buffer 有一个固定的大小值,也叫做 “capactiy” . 你只能往里面写 capacity 个 byte


long、 char等类型。一旦 buffer 满了,需要将其清空(通过读数据或者清除数据)才能继续写数据往里写数据。


(2) postition


1)写数据到 Bufer 中时,position 表示写入数据的当前位置,position 的初始值为 0 。当一个 byte,long,等数据写入到 buffer 后,position 会向下移动到下一个可插入的元素的 buffer 但愿。position 最大可为 capacity -1 (因为 position 的初始值为 0)


2)读数据到 Buffer 中时,position 表示读数据的当前位置,如 position = 2 时表示已经开始读了 3 个 byte, 或者从第三个 byte 开始读取,通过 ByteBuffer.flip() 切换到读模式 position 会被重置为 0, 当 Buffer 从 position 读入数据后,position 会下移到下一个可读入的数据 Buffer 单元。


(3) limit


1)写数据时, limit 表示可以对 Buffer 最多写入多少个数据。写模式下,limit 等于 Buffer 的 capactiy


2)读数据时, limit 表示 Buffer 里有多少可读数据(not null 的数据),因此能读取到之前写入的所有数据(limit 被设置为已写数据的数量,这个值在写模式下就是 position)


Buffer 的类型


Java NIO 有一下 Buffer 的类型


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


这些 buffer 类型都代表了不同的数据类型。换句话说,就是可以通过 char ,short, int, long , float 或者 double 类型来操作缓冲区的字节。


Buffer 分配和写数据


1、 Buffer 分配


想要获取一个 Buffer 对象首先要进行分配。每一个 Buffer 类都有一个 allocate 方法。

下面是一个分配 48 字节 capactiy 的 ByteBuffer 的例子。


ByteBuffer buf = ByteBuffer.alloacte(48);


这是分配一个可存储 1024 个字符的 CharBuffer:


ByteBuffer buf = ByteBuffer.alloacte(1024);


相关文章
|
1月前
|
存储 Java 数据处理
|
1月前
|
Java API
java中IO与NIO有什么不同
java中IO与NIO有什么不同
|
7天前
|
监控 Java 开发者
深入理解 Java 网络编程和 NIO
【4月更文挑战第19天】Java网络编程基于Socket,但NIO(非阻塞I/O)提升了效率和性能。NIO特点是非阻塞模式、选择器机制和缓冲区,适合高并发场景。使用NIO涉及通道、选择器和事件处理,优点是高并发、资源利用率和可扩展性,但复杂度、错误处理和性能调优是挑战。开发者应根据需求选择是否使用NIO,并深入理解其原理。
C4.
|
1月前
|
存储 安全 Java
Java的字符串缓冲区
Java的字符串缓冲区
C4.
13 0
|
2月前
|
移动开发 编解码 网络协议
用Java的BIO和NIO、Netty来实现HTTP服务器(三) 用Netty实现
用Java的BIO和NIO、Netty来实现HTTP服务器(三) 用Netty实现
|
2月前
|
网络协议 Java Linux
用Java来实现BIO和NIO模型的HTTP服务器(二) NIO的实现
用Java来实现BIO和NIO模型的HTTP服务器(二) NIO的实现
|
2月前
|
编解码 网络协议 Java
用Java的BIO和NIO、Netty实现HTTP服务器(一) BIO与绪论
用Java的BIO和NIO、Netty实现HTTP服务器(一) BIO与绪论
|
3月前
|
Java 应用服务中间件 Linux
java中的NIO,BIO,AIO
java中的NIO,BIO,AIO
17 0
|
3月前
|
设计模式 网络协议 Java
Java NIO 网络编程 | Netty前期知识(二)
Java NIO 网络编程 | Netty前期知识(二)
77 0
|
3月前
|
Java 索引
📌 Java NIO Buffer
Java NIO缓冲区在与NIO通道交互时使用。数据从通道读取到缓冲区,然后从缓冲区写入通道。 缓冲区本质上是一块内存,可以在其中写入数据,然后再进行读取。这个内存块被封装在一个NIOBuffer对象中,该对象提供了一组方法,可以更容易地使用内存块。