📌 Java NIO Buffer

简介: Java NIO缓冲区在与NIO通道交互时使用。数据从通道读取到缓冲区,然后从缓冲区写入通道。缓冲区本质上是一块内存,可以在其中写入数据,然后再进行读取。这个内存块被封装在一个NIOBuffer对象中,该对象提供了一组方法,可以更容易地使用内存块。

Java NIO缓冲区在与NIO通道交互时使用。数据从通道读取到缓冲区,然后从缓冲区写入通道。

缓冲区本质上是一块内存,可以在其中写入数据,然后再进行读取。这个内存块被封装在一个NIOBuffer对象中,该对象提供了一组方法,可以更容易地使用内存块。

Buffer基础用法:

  1. 写入数据到Buffer缓冲区中
  2. 调用buffer.flip(),转换Buffer缓冲区读写模式
  3. Buffer缓冲区中读取数据
  4. 调用buffer.clear()buffer.compact()对缓冲区数据进行处理
// 使用缓存区进行内存分配:
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
// 从Channel中读取数据,写入到Buffer中:
int read = fileChannel.read(byteBuffer);
while (-1 != read) {
    // flip转换读写模式:
    byteBuffer.flip();
    while (byteBuffer.hasRemaining()) {
        System.out.print((char) byteBuffer.get());
    }
    // 清除缓冲区内容:
    byteBuffer.clear();
    read = fileChannel.read(byteBuffer);
}

将数据写入缓冲区时,缓冲区会跟踪写入的数据量。一旦需要读取数据,就需要使用flip()方法调用将缓冲区从写入模式切换到读取模式。在读取模式下,缓冲区允许您读取写入缓冲区的所有数据。

一旦读取了所有数据,就需要清除缓冲区,以便再次写入。可以通过两种方式来实现:通过调用clear()或通过调用compact()clear()方法清除整个缓冲区。compact()方法只清除您已经读取的数据。任何未读数据都会移动到缓冲区的开头,现在数据将在未读数据之后写入缓冲区。

Buffer核心属性:

缓冲区有三个您需要熟悉的属性:capacity缓冲区容量position指针索引位置limit缓冲区限制

position位置和limit限制的含义取决于缓冲区是处于读取模式还是写入模式。无论缓冲模式如何,capacity容量含义不变。

public abstract class Buffer {
  // ......
    // Invariants: mark <= position <= limit <= capacity
    private int mark = -1;  // 标记
    private int position = 0;
    private int limit;
    private int capacity;
}
  1. Capacity容量:

Buffer作为一个内存块,缓冲区有一定的固定大小,也称为“容量”。只能将容量字节、长度、字符等写入缓冲区。一旦缓冲区已满,就需要清空它(读取数据或清除它),然后才能向其中写入更多数据。

  1. Position指针位置:

指针位置,下一个要被读或写的元素索引,每次读写缓冲区数据时都会改变值,为下次读写做准备。

将数据写入缓冲区时,会在某个位置进行写入。最初位置为0。当一个字节、长等已写入缓冲区时,该位置将前进到指向缓冲区中的下一个单元格以插入数据。位置可以最大化为容量-1

当从缓冲区读取数据时,也可以从给定的位置读取数据。将“缓冲区”从写入模式翻转到读取模式时,位置会重置回0。当从缓冲区读取数据时,从位置读取数据,位置将前进到下一个要读取的位置。

  1. limit缓冲区限制:

表示缓冲区的当前终点,不能对缓冲区超过极限的位置进行读写操作。且极限是可以修改的。

在写入模式下,缓冲区的限制是可以写入缓冲区的数据量的限制。在写入模式下,限制等于缓冲区的容量。

将“缓冲区”切换到读取模式时,limit表示可以从数据中读取多少数据的限制。所以,当将缓冲区翻转到读取模式时,将限制设置为写入模式的写入位置。换句话说,可以读取写入的字节数(限制设置为写入的字节数量,由位置标记)。

Buffer常用类型:

Java NIO具有以下缓冲区类型:

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

Buffer分配内存(创建Buffer实例):

要获得Buffer对象,您必须首先对其进行分配。每个Buffer类都有一个allocate()方法来完成此操作。

ByteBuffer分配1024字节内存:

// 给Buffer分配内存:
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);

CharBuffer分配1024字符:

CharBuffer charBuffer = CharBuffer.allocate(1024);

Buffer中写入数据:

可以通过两种方式向缓冲区中写入数据:

  • 可以从Channel通道中获取到数据,写入Buffer缓冲区。
// 读取Channel中的数据到Buffer中:
int bytesRead = inChannel.read(buf);
  • 可以通过调用put()方法,直接写入数据到Buffer缓冲区中。
buf.put(127);

flip()方法 转换Buffer读写模式:

flip()方法可以转换Buffer的读写模式,将Buffer从写入模式切换到读取模式,调用flip()可以将position设置为0,并将limit设置为些时的position位置。

换句话说,position现在标记读取位置,limit标记有多少字节、字符等被写入缓冲区(可以读取的字节、字符等等的限制)。

Buffer中读取数据:

可以通过两种方式从缓冲区中读取数据:

  • 可以读取Buffer中的数据到Channel中。
// 向通道中写入数据:
int bytesWritten = inChannel.write(buf);
  • 可以通过get()方法获取到Buffer中的数据。
byte aByte = buf.get();

Buffer还提供了额外方法用于操作positionlimit等属性的方法:

  • reword()

Buffer.rewind()position位置设置回0,这样您就可以重新读取缓冲区中的所有数据。限制保持不变,因此仍然标记可以从缓冲区读取多少元素(字节、字符等)。

  • mark()reset()

mark() 是在读取时,做一个标记,即使 position 改变,只要调用 reset() 就能回到 mark 的位置。注意:rewind()flip() 都会清除 mark 位置。

buffer.mark();
//call buffer.get() a couple of times, e.g. during parsing.
buffer.reset();  //set position back to mark.
  • clear()compact()

一旦完成了从缓冲区中读取数据,就必须使缓冲区做好再次写入的准备。您可以通过调用clear()compact()来实现这一点。

如果调用clear(),则位置将设置回0,并限制容量。换句话说,缓冲区被清除。缓冲区中的数据不会被清除。只有指示可以将数据写入缓冲区的位置的标记。

当您调用clear()时,如果缓冲区中有任何未读数据,则该数据将被“遗忘”,这意味着您不再有任何标记来指示哪些数据已被读取,哪些数据未被读取。

如果缓冲区中仍有未读数据,并且您想稍后读取,但需要先进行一些写入,请调用compact()而不是clear()

compact()将所有未读数据复制到Buffer的开头。然后它将位置设置在最后一个未读元素的正后方。limit属性仍然设置为capacity,就像clear()一样。现在缓冲区已准备好写入,但不会覆盖未读数据。

  • equals()compareTo()

equals()两个缓冲区相等,如果:它们属于相同的类型(字节、字符、int等)它们在缓冲区中具有相同数量的剩余字节、字符等。所有剩余的字节、字符等都是相等的。正如您所看到的,equals只比较Buffer的一部分,而不是其中的每一个元素。事实上,它只是比较Buffer中的其余元素。

compareTo()方法比较两个缓冲区的剩余元素(字节、字符等),用于例如排序例程。如果出现以下情况,则认为缓冲区比另一个缓冲区“小”:与另一个缓冲器中的对应元素相等的第一个元素小于另一个缓冲区中的元素。所有元素都是相等的,但第一个缓冲区在第二个缓冲区之前用完了元素(它的元素更少)。

相关文章
|
7天前
|
存储 监控 Java
Java的NIO体系
通过本文的介绍,希望您能够深入理解Java NIO体系的核心组件、工作原理及其在高性能应用中的实际应用,并能够在实际开发中灵活运用这些知识,构建高效的Java应用程序。
26 5
|
5月前
|
Java 大数据
解析Java中的NIO与传统IO的区别与应用
解析Java中的NIO与传统IO的区别与应用
|
1月前
|
消息中间件 缓存 Java
java nio,netty,kafka 中经常提到“零拷贝”到底是什么?
零拷贝技术 Zero-Copy 是指计算机执行操作时,可以直接从源(如文件或网络套接字)将数据传输到目标缓冲区, 而不需要 CPU 先将数据从某处内存复制到另一个特定区域,从而减少上下文切换以及 CPU 的拷贝时间。
java nio,netty,kafka 中经常提到“零拷贝”到底是什么?
|
2月前
|
Java
让星星⭐月亮告诉你,Java NIO之Buffer详解 属性capacity/position/limit/mark 方法put(X)/get()/flip()/compact()/clear()
这段代码演示了Java NIO中`ByteBuffer`的基本操作,包括分配、写入、翻转、读取、压缩和清空缓冲区。通过示例展示了`position`、`limit`和`mark`属性的变化过程,帮助理解缓冲区的工作原理。
37 2
|
3月前
|
存储 网络协议 Java
Java NIO 开发
本文介绍了Java NIO(New IO)及其主要组件,包括Channel、Buffer和Selector,并对比了NIO与传统IO的优势。文章详细讲解了FileChannel、SocketChannel、ServerSocketChannel、DatagramChannel及Pipe.SinkChannel和Pipe.SourceChannel等Channel实现类,并提供了示例代码。通过这些示例,读者可以了解如何使用不同类型的通道进行数据读写操作。
Java NIO 开发
|
2月前
|
缓存 Java
java文件读取 while ((len = reader.read(buffer)) != -1){}的理解
本文解释了Java中使用`InputStreamReader`和`read(buffer)`方法循环读取文件内容的机制,强调了如何正确理解读取循环和处理读取到的数据,以及如何处理字符编码和换行符。
54 0
|
4月前
|
Java
"揭秘Java IO三大模式:BIO、NIO、AIO背后的秘密!为何AIO成为高并发时代的宠儿,你的选择对了吗?"
【8月更文挑战第19天】在Java的IO编程中,BIO、NIO与AIO代表了三种不同的IO处理机制。BIO采用同步阻塞模型,每个连接需单独线程处理,适用于连接少且稳定的场景。NIO引入了非阻塞性质,利用Channel、Buffer与Selector实现多路复用,提升了效率与吞吐量。AIO则是真正的异步IO,在JDK 7中引入,通过回调或Future机制在IO操作完成后通知应用,适合高并发场景。选择合适的模型对构建高效网络应用至关重要。
94 2
|
4月前
|
网络协议 C# 开发者
WPF与Socket编程的完美邂逅:打造流畅网络通信体验——从客户端到服务器端,手把手教你实现基于Socket的实时数据交换
【8月更文挑战第31天】网络通信在现代应用中至关重要,Socket编程作为其实现基础,即便在主要用于桌面应用的Windows Presentation Foundation(WPF)中也发挥着重要作用。本文通过最佳实践,详细介绍如何在WPF应用中利用Socket实现网络通信,包括创建WPF项目、设计用户界面、实现Socket通信逻辑及搭建简单服务器端的全过程。具体步骤涵盖从UI设计到前后端交互的各个环节,并附有详尽示例代码,助力WPF开发者掌握这一关键技术,拓展应用程序的功能与实用性。
150 0
|
5月前
|
安全 Java Linux
(七)Java网络编程-IO模型篇之从BIO、NIO、AIO到内核select、epoll剖析!
IO(Input/Output)方面的基本知识,相信大家都不陌生,毕竟这也是在学习编程基础时就已经接触过的内容,但最初的IO教学大多数是停留在最基本的BIO,而并未对于NIO、AIO、多路复用等的高级内容进行详细讲述,但这些却是大部分高性能技术的底层核心,因此本文则准备围绕着IO知识进行展开。
190 1
|
4月前
|
存储 网络协议 Java
【Netty 神奇之旅】Java NIO 基础全解析:从零开始玩转高效网络编程!
【8月更文挑战第24天】本文介绍了Java NIO,一种非阻塞I/O模型,极大提升了Java应用程序在网络通信中的性能。核心组件包括Buffer、Channel、Selector和SocketChannel。通过示例代码展示了如何使用Java NIO进行服务器与客户端通信。此外,还介绍了基于Java NIO的高性能网络框架Netty,以及如何用Netty构建TCP服务器和客户端。熟悉这些技术和概念对于开发高并发网络应用至关重要。
89 0