前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >第三节 netty前传-NIO中缓冲buffer-01

第三节 netty前传-NIO中缓冲buffer-01

作者头像
用户1418372
发布2018-10-22 16:00:07
3090
发布2018-10-22 16:00:07
举报
文章被收录于专栏:清晨我上码清晨我上码

Buffers

缓冲区(Buffers)本质上是一个可以写入数据的内存块,然后可以读取。 这个内存块包含在NIO Buffer对象中,该对象提供了一组api,这样可以方便用户更轻松地使用内存块。

在NIO中已实现的buffer类中继承Buffer这个抽象类

代码语言:javascript
复制
public abstract class Buffer {
    // Cached unsafe-access object
    static final Unsafe UNSAFE = Unsafe.getUnsafe();
    /**
     * The characteristics of Spliterators that traverse and split elements
     * maintained in Buffers.
     */
    static final int SPLITERATOR_CHARACTERISTICS =
        Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.ORDERED;

    // Invariants: mark <= position <= limit <= capacity
    private int mark = -1;
    private int position = 0;
    private int limit;
    private int capacity;
//略。。。
}

其他具体的实现方式,根据不同的需求实现例如 ByteBuffer底层使用的为byte数组 CharBuffer使用char数组 DirectByteBuffer使用直接内存,这里通过从抽象类中的Unsafe 类分配直接内存使用。

  • 缓冲的基本用法:下面是最基本的四步
  1. 向buffer写入数据
  2. 调用buffer.flip() 方法反转
  3. 读取buffer中的数据
  4. 调用buffer.clear() 或者buffer.compact()清楚

当数据写入缓冲区时,缓冲区会跟踪写入的数据量(在buffer对象中有position 会跟踪写入点)。 一旦需要读取数据,就需要使用flip() 方法调用将缓冲区从写入模式切换到读模式。 在读模式下,缓冲区允许读取已经写入缓冲区的所有数据。一旦读完所有数据,需要清除缓冲区,以便再次写入。 可以通过两种方式执行:调用clear()或调用compact() 方法。 clear() 方法清除整个缓冲区。 compact()方法仅清除已读取的数据。 任何还没读的数据都会移动到缓冲区的开头,接下来写入时,就会在这些未读数据之后写入。 下面用一个简单的例子来说明

代码语言:javascript
复制
public class ReadFile {
    public static void main(String[] args){
        readFile();
    }
    public static void readFile(){
        try(RandomAccessFile randomAccessFile =
                    new RandomAccessFile("F:\\data\\test.txt","rw")){
            //获取连接通道
            FileChannel fileChannel = randomAccessFile.getChannel();
            //初始化一个缓冲区,大小为1024byte
            ByteBuffer buf = ByteBuffer.allocate(1024);
            //fileChannel.read(buf)从通道中读取文件的数据放入缓冲区,返回结构为读取的字节数
            //注意:这个方法会记录读取的位置,所以后续读取不会从头开始读取
            int bytesRead = fileChannel.read(buf);
            System.out.println(bytesRead);
            //读取到数据
            while(bytesRead != -1)
            {
                //反转后为可以读取缓冲中的数据
                buf.flip();
                while(buf.hasRemaining())//position < limit;表示可读
                {
                    //读取
                    System.out.print((char)buf.get());
                }
                //没有可读数据后,清除已读数据,从未读数据之后开始写入
                buf.compact();
                //开始继续读取
                bytesRead = fileChannel.read(buf);
            }
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}

说明Buffer 中的Capacity, Position 和Limit之间的关系

如下图分别表示写入和读取操作的buffer

图片.png

  • Capacity 缓冲区具有一定的固定大小,也称为“容量”。 表示缓冲区的大小,也是buffer所能存储的最大容量
  • Position 写操作: 在数据写入缓冲区的时候,可以选择在某个位置执行此写入操作。 如果写入时没有选择相应的位置,会默认从最初位置0开始写入,每当一个字节,字符或者整数等等写入缓冲区时,position会自动被指向缓冲区中的下一个单元为了下次插入数据。 位置最大可以变为容量 -1。为-1时表示已经写满了,不可再写入。 读操作: 从缓冲区读取数据时,也可以从指定的位置开始读取数据。 当缓冲区从写入模式翻转到读取模式时(调用flip方法),位置position将重置为0.。同理,当从缓冲区读取数据时,将从position位置开始读取数据,并将自动将position移动到下一个要读取的位置。
  • Limit 写模式: limit的作用是限制写入缓冲区的数据量。写入时等于Capacity大小 读模式:缓冲区翻转为读取模式时,限制意味着可以从数据中读取的数据量的限制。 所以,当Buffer翻转到读取模式时,limit会被设置为写模式的写入位置。 换句话说,就是可以读取写入的字节数(限制设置为写入的字节数,由位置标记)。

关于Buffer中方法下一节详解

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018.10.16 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Buffers
  • 说明Buffer 中的Capacity, Position 和Limit之间的关系
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档