Java NIO 笔记02

Java NIO 笔记02

更多内容:我的博客

Java NIO Buffer

Java NIO Buffer 在与Channel交互时被使用——channel从buffer中读取数据,channel将数据写入buffer。

一个buffer本质上是一块内存区域,我们可以在其中写入数据,之后可以再次读取数据。这个内存块被包裹在NIO 的 Buffer对象中。它提供了一些方法可以轻松的使用内存块。

Buffer的基本使用

使用Buffer进行读取和写入一般有如下4个步骤:

  1. 将数据写入Buffer
  2. 调用buffer.flip()方法
  3. 从缓冲区读取数据集
  4. 调用buffer.clear()或者buffer.compact()方法

当你把数据写入buffer时,buffer会记录写了多少数据。一旦你需要读取数据,我们需要调用flip()方法将buffer从写入模式切换为读取模式。在读取模式下,缓冲区允许读取写入缓冲区的所有数据。

读取完数据后,需要清楚缓冲区,使其准备好再次写入。实现它有俩种方法——调用clear()方法或者compact()方法。其中clear()方法会清除整个buffer。compact()方法只清除已经读过的数据。任何未读数据都将移动到buffer的开头,数据将在未读数据之后写入缓冲区。

RandomAccessFile aFile = new RandomAccessFile("data/nio-data.txt","rw");
FileChannel inChannel = new FileChannel();
//创建容量为48字节的缓冲区
ByteBuffer buf = ByteBuffer.allocate(48);
//读入缓冲区
int bytesRead = inChannel.read(buf);
while(bytesRead != -1){
    buf.flip();	//make buffer ready for read (使缓冲区准备读取)
    while(buf.hasRemaining()){
        System.out.print((char) buf.get()); //一次读取一个字节
    }
    buf.clear();	//make buffer ready for writing (使缓冲区准备好写入)
    bytesRead = inChannel.read(buf);
}
aFile.close();
Buffer 的容量(capacity)、位置(position)和限制(limit)

为了理解缓冲区是如何工作的有三个我们需要熟悉的属性,它们是:

  • capacity (容量)
  • position (位置)
  • limit (限度)

position和limit的含义取决于Buffer是处于读模式还是写模式,容量的含义和它处于何种模式无关。

Buffer2

capacity

作为一个内存块,Buffer有固定的大小,也成为容量(capacity)。一旦Buffer已满,这时,需要我们清空它,然后才能继续将更多的数据写入其中。

position

当我们是处于写入模式时,即将数写入Buffer中时,position表示正在写入的位置,它最初时为0。当我们写入数据时,position将前进指向下一个单元格将数据插入。position的最大限度是(capacity - 1)

当我们是处于读取模式时,即读取数据从Buffer时,position表示正在读取的位置,当通过flip将模式由写入模式翻转到读取模式时,position将重置为0,读取数据是是从当前position读取数据并且position前进到下一个位置。

limit

在写入模式下,limit表示我们可以写入多少数据到buffer中,所以在写入模式下它与容量(capacity)是相等的。

在读取模式下,limit表示我们可以从数据中读取多少数据的限制,因此在读取模式下limit设置为写入模式的position,也就是读取与写入与一样多的数据。

分配Buffer

要想获得一个Buffer首先必须分配它,每一个Buffer类中的allocate()方法就是来做这件事情的,下面是示例:

ByteBuffer buf = ByteBuffer.allocate(48);	//分配一个48字节的ByteBuffer缓冲区
CharBuffer cuf = CharBuffer.allocate(1024);	//分配一个1024个字符空间的CharBuffer缓冲区
写入数据到Buffer

将数据写入Buffer有俩种方法:

  • 将数据从通道写入Buffer区
  • 通过Buffer的put()方法自己将数据写入缓冲区
int bytesRead = inChannel.read(buf);	//read into buffer;
buf.put(127);
flip()

flip()方法将Buffer从写入模式转为读取模式,调用flip()方法会将position重新设置为0,并将limit设置为刚刚写入模式时的position位置。

从Buffer读取数据

从Buffer读取数据也有俩总方法:

  • 将Buffer中的数据读取到Channel中
  • 使用Buffer自带的get()方法读取数据。
//read from buffer into channel
int bytesRead = inChannel.write(buf);
byte aByte = buf.get();
rewind()

Buffer中rewind()方法可以将position重新设置为0,因此我们可以重新读取缓冲区中的所有数据。limit不会发生改变,因此也可以获取缓冲区中数据的数量。

clear()和compact()

当从Buffer中读取完完数据后必须将Buffer再次准备为可写模式,这里可是使用clear()方法和compact()方法,clear()会清空这个buffer的数据,此时position为0,limit为buffer的capacity。compact()方法只会清除已读取的数据,compact()方法将所有未读的数据移动到开头,此时position会设置为未读数据的最后一个元素之后,limit和使用clear()方法一样,还是capacity。这样我们就可以再次写入数据而不会覆未读取的数据。

mark() 和 reset()

我们可以通过Buffer中的mark()方法来标记给定的position,然后可以通过reset()方法重置回给定标记的位置,例如:

buffer.mark();
//调用几次get()方法
buffer.reset();	//重新设置position到mark的位置
equals() and compareTo()

可以使用equals和compareTo()比较俩个buffer。

equals()

如果满足有以下条件则俩个buffer是相等的:

  • 它们属于同一种类型(byte、char、int等)
  • 它们在缓冲区中具有相同的剩余字节或字符等。
  • 所有剩余的字节、字符等都是相等的。

如上所述,equals只比较缓冲区的一部分,而不是其中的每个元素。实际上,它只是比较Buffer中的剩余元素。

compareTo()

compareTo()方法比较俩个缓冲区的剩余元素(字符、字节等)。例如用于排序的程序中,在以下情况时,缓冲区被认为比另一个缓冲区小:

  • 与另一个缓冲区中的相应元素相等的第一个元素小于另一个缓冲区中的元素。
  • 所有元素都是相等的,但第一个缓冲区在第二个缓冲区之前用完元素(它有更少的元素)。

更多内容:我的博客

posted @   胡海龙  阅读(17)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
www.huhailong.vip
点击右上角即可分享
微信分享提示