Mr丶冷文

文章 分类 评论
125 10 8391

站点介绍

冷文学习者(KEVINLU98.COM),记录一个北漂小码农的日常业余生活
友链申请地址(直接评论即可): 传送门

NIO中Buffer的基本原理

MR丶冷文 2021-04-29 2667 0条评论 技术学习 学习缓冲区bufferjavanio

首页 / 正文
Freewind主题v1.5版本已发布,下载请移步Freewind 1.5,同时还有主题伴生插件Freewind Markdown,下载请移步 Freewind Markdown,有问题请在留言板,交换友链请直接在友链留言,我创建了一个主题交流群,有兴趣可以加下: 点此加入
报毒我说明一下,是因为我把主题的版权信息做了加密,其中用了eval,杀毒软件认为eval函数是一个危险的操作,这点介意的话请勿下载,我也没有强迫任何人去下载,也没有向大家收取一分钱的主题费用,所以也犯不着因为这些事情来喷我,喜欢就用,不喜欢就不用,就这么简单

发布于2022-10-28

Buffer的基本原理

我们说的缓冲区本质上是一个数组,但它其实是一个特殊的数组,缓冲区对象内置了一些机制,能够跟踪和记录缓冲区的状态变化情况,如果我们使用get()方法从缓冲区获取数据或者使用put()方法把数据写入缓冲区,都会引起缓冲区状态变化。

在缓冲区中,最重要的属性有下面三个,它们一起合作完成对缓冲区内部的变化跟踪

  • position:指定下一个将要写入或者读取的元素索引,它的值由get()/put()方法自动更新,在新创建一个Buffer对象时,position被初始化为0
  • limit:指定还有多少数据需要取出(在从缓冲区写入通道时),或者还有多少空间可以放入数据(在从通道读入缓冲区时)
  • capacity:指定了可以存储在缓冲区中的最大数据容量,实际上,它指定了底层数组的大小,或者至少是指定了准许我们使用的底层数组的容量

这三个属性之间有一些相对大小的关系:0<=position<=limit<=capacity。

举例说明

我们现在需要取读磁盘的一个文件,文件内容如下:
lengwen

我们创建一个新的容量大小为10的ByteBuffer对象,在初始化时将position设置为0,limit和capacity设置为10,在以后使用ByteBuffer对象的过程中,capacity的值不在变化,而其他两个将会随着使用而变化。

https://imagebed-1252410096.cos.ap-nanjing.myqcloud.com/20210429/63ea1f29477e4dd3a7e1916c774f8945.png

我们现在要读文件,对于缓冲区来说,是将数据从inputstream的通道中写到缓冲区, 可以看出我们文件中数据的长度为7,此时往缓冲区写完后position的值为7,即下一个将要被写入的字节索引为7.而limit仍为10

https://imagebed-1252410096.cos.ap-nanjing.myqcloud.com/20210429/23b6f089da22442d9c72cd4c6b5580e0.png

下一步是将数据写入到输出的通道,对于缓冲区来说,就是从缓冲区中读取数据,但在些之前,必须调用flip()方法。该方法将会完成以下两件事情:(1)把limit设置为当前的position值;(2)把position设置为0

解释:由于position被设置为0,所以可以保证在下一步输出时读取的是缓冲区的第一个字节,而limit被设置为当前的position,可以保证读取的数据正好是之前写入缓冲区的数据

https://imagebed-1252410096.cos.ap-nanjing.myqcloud.com/20210429/89ac67ec210040519684e941ad8be487.png

现在调用git()方法从缓冲区中读取数据写入输出通道,这会导致position的增加而limit保持不变,但position不会超过linit的值,所以在读取之前写入缓冲区的7字节之后,position和limit的值都为7

https://imagebed-1252410096.cos.ap-nanjing.myqcloud.com/20210429/9d7f48759a9c40e089b504c204745801.png

在从缓冲区读取完成之后,limit的值仍然为7,此时调用clear()方法能够把所有的状态变化设置为初始化时的值

https://imagebed-1252410096.cos.ap-nanjing.myqcloud.com/20210429/63ea1f29477e4dd3a7e1916c774f8945.png

举例代码

上面说明了使用缓冲区读取文件的全过程,现在去实现一下上述过程

package cn.kevinlu98.netty.buffer;

import java.io.FileInputStream;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

/**
 * Author: 鲁恺文
 * Date: 2021/4/29 3:48 下午
 * Email: lukaiwen@xiaomi.com
 * Description:
 */
public class BufferReadFile {
    public static void main(String[] args) throws IOException {
        //这里用的是文件I/O处理
        FileInputStream fis = new FileInputStream("/Users/lengwen/Desktop/buffer.txt");
        //创建文件的操作管道
        FileChannel channel = fis.getChannel();
        //分配一个10大小的缓冲区,其实就是分配一个10个大小的Byte数组
        ByteBuffer buffer = ByteBuffer.allocate(10);
        printInfo("初始化", buffer);
        //将数据从通道中写到缓冲区
        channel.read(buffer);
        printInfo("调用read", buffer);
        //把limit设置为当前的position值;把position设置为0
        buffer.flip();
        printInfo("调用flip", buffer);
        while (buffer.remaining() > 0) {
            byte b = buffer.get();
            System.out.print((char) b);
        }
        printInfo("调用完get", buffer);
        //调用clear恢复position limit

        buffer.clear();
        printInfo("调用clear", buffer);

        fis.close();
    }

    private static void printInfo(String step, ByteBuffer buffer) {
        System.out.println();
        System.out.println("step:"+step);
        System.out.println("\tcapacity:" + buffer.capacity());
        System.out.println("\tposition:" + buffer.position());
        System.out.println("\tlimit:" + buffer.limit());
    }
}

运行结果

step:初始化
    capacity:10
    position:0
    limit:10

step:调用read
    capacity:10
    position:7
    limit:10

step:调用flip
    capacity:10
    position:0
    limit:7
lengwen
step:调用完get
    capacity:10
    position:7
    limit:7

step:调用clear
    capacity:10
    position:0
    limit:10

评论(0)

热门文章

最新评论

  • 1

    看看

  • eeee

    多谢大佬分享

  • asdasd

    强强强

  • asdasd

    感谢作者!

  • asdasd

    感谢!

日历

2024年11月

     12
3456789
10111213141516
17181920212223
24252627282930

文章目录

站点公告
Freewind主题v1.5版本已发布,下载请移步Freewind 1.5,同时还有主题伴生插件Freewind Markdown,下载请移步 Freewind Markdown,有问题请在留言板,交换友链请直接在友链留言,我创建了一个主题交流群,有兴趣可以加下: 点此加入
报毒我说明一下,是因为我把主题的版权信息做了加密,其中用了eval,杀毒软件认为eval函数是一个危险的操作,这点介意的话请勿下载,我也没有强迫任何人去下载,也没有向大家收取一分钱的主题费用,所以也犯不着因为这些事情来喷我,喜欢就用,不喜欢就不用,就这么简单
点击小铃铛关闭