Buffer之position,limit,capacity

一、前言

熟悉NIO的人想必一定不会陌生buffer中position,limit,capacity这三个属性吧,之前在学习的时候遇到一个问题:就是当你先往缓冲区写入一部分数据,然后调用flip()方法,再全部读取完数据,然后再调用flip()方法,此时这三个值的变化是怎样的,研究了一下,决定写下来分享一下。

二、正文

1、介绍

position: 它指的是下一次读取或写入的位置。

limit: 指定还有多少数据需要写出(在从缓冲区写入通道时),或者还有多少空间可以读入数据(在从通道读入缓冲区时),它初始化是与capacity的值一样,当调用flip()方法之后,它的值会改变成position的值,而position被置0。它箭头所指的位置是最后一位元素的下一位所在的位置*

capacity: 指定了可以存储在缓冲区中的最大数据容量,实际上,它指定了底层数组的大小,或者至少是指定了准许我们使用的底层数组的容量,这个初始化后就不会再改变了。

2、图示

以上三个属性值之间有一些相对大小的关系:0 <= position <= limit <= capacity。如果我们创建一个新的容量大小为7的ByteBuffer对象,在初始化的时候,position设置为0,limit和 capacity被设置为7,在以后使用ByteBuffer对象过程中,capacity的值不会再发生变化,而其它两个个将会随着使用而变化。三个属性值分别如图所示:

初始化:

假设我们现在要往这个缓冲区里面写入3个字节,写完之后,position的箭头就会指向3的位置,而limit不变:

此时我们想从缓冲区读取这3个字节,就必须调用flip()方法,调用了flip()方法过后,limit置为position的位置,而position被置为0,也正应证了上面所说的,position它指的是下一次读取或写入的位置,limit它箭头所指的位置是最后一位元素的下一位所在的位置:

现在我们可以调用get()方法,一直从缓冲区里面取数据,直到取完为止,也就是当position与limit的值一样时,就取完了:

这一次简单的读写操作就完成了,如果想恢复成初始状态的话,可以调用clear()方法:

之前学到这里的时候有个疑问,不知道大家想过没有,就是我们在调用了get()方法从缓冲区取完里面的数据,立马去调用flip()方法,那这三个属性的值会是什么变化?如果当我只读了2个字节的数据之后,就不读了,然后再去调用flip(),这三个值又会是怎么变化?其实不管怎么绕,你只要懂得原理,就不难,咱们先看flip()源代码做了什么:

public final Buffer flip() {

        limit = position;

        position = 0;

        mark = -1;

        return this;

    }

这里不难发现,调用flip()方法,无非就是给这几个变量赋值,将当前的position值赋给limit,然后将position的值置为0,Mark是一个标志变量,咱们以后会提到。熟悉以上代码就不难解决我提出的2个问题:

当你读取完调用flip()的方法      positon:0    limit:3  capacity:7

当你读取2个字节之后调用flip()方法      positon:0    limit:2  capacity:7

这里就解决了我之前遇到的这三个属性值变化的问题!!!

三、测试代码

读取完调用flip:

package com.cing.nio;

import java.io.FileInputStream;

import java.nio.Buffer;

import java.nio.ByteBuffer;

import java.nio.channels.FileChannel;

public class NioTest1 {

    public static void main(String[] args) throws Exception{

        FileInputStream fis = new FileInputStream("D:\\A.txt");

        FileChannel fc = fis.getChannel();

        ByteBuffer buffer = ByteBuffer.allocate(7);

        output("初始化", buffer);

        fc.read(buffer);

        output("调用READ方法", buffer);

        buffer.flip();

        output("第一次调用flip", buffer);

        while (buffer.remaining() > 0) {

            byte b = buffer.get();

        }

        output("get()", buffer);

        buffer.flip();

        output("第二次flip", buffer);

        fis.close();

    }

    public static void output(String step, Buffer buffer) {

        System.out.println(step + " : ");

        System.out.println("buffer: " + buffer + ", ");

    }

}

输出结果为:

初始化 :

buffer: java.nio.HeapByteBuffer[pos=0 lim=7 cap=7],

调用READ方法 :

buffer: java.nio.HeapByteBuffer[pos=3 lim=7 cap=7],

第一次调用flip :

buffer: java.nio.HeapByteBuffer[pos=0 lim=3 cap=7],

get() :

buffer: java.nio.HeapByteBuffer[pos=3 lim=3 cap=7],

第二次flip :

buffer: java.nio.HeapByteBuffer[pos=0 lim=3 cap=7],

读取2字节之后调用flip:

package com.cing.nio;

import java.io.FileInputStream;

import java.nio.Buffer;

import java.nio.ByteBuffer;

import java.nio.channels.FileChannel;

public class NioTest1 {

    public static void main(String[] args) throws Exception{

        FileInputStream fis = new FileInputStream("D:\\A.txt");

        FileChannel fc = fis.getChannel();

        ByteBuffer buffer = ByteBuffer.allocate(7);

        output("初始化", buffer);

        fc.read(buffer);

        output("调用READ方法", buffer);

        buffer.flip();

        output("第一次调用flip", buffer);

        while (buffer.remaining() > 1) {

            byte b = buffer.get();

        }

        output("get()", buffer);

        buffer.flip();

        output("第二次flip", buffer);

        fis.close();

    }

    public static void output(String step, Buffer buffer) {

        System.out.println(step + " : ");

        System.out.println("buffer: " + buffer + ", ");

    }

}

输出结果为:

初始化 :

buffer: java.nio.HeapByteBuffer[pos=0 lim=7 cap=7],

调用READ方法 :

buffer: java.nio.HeapByteBuffer[pos=3 lim=7 cap=7],

第一次调用flip :

buffer: java.nio.HeapByteBuffer[pos=0 lim=3 cap=7],

get() :

buffer: java.nio.HeapByteBuffer[pos=2 lim=3 cap=7],

第二次flip :

buffer: java.nio.HeapByteBuffer[pos=0 lim=2 cap=7],

NIO的知识学起来还是比较有趣的,期待下次与大家分享这块的知识!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容