一、前言

熟悉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的知识学起来还是比较有趣的,期待下次与大家分享这块的知识!

Buffer之position,limit,capacity相关推荐

  1. 【Java Netty】Java NIO position limit capacity 以及 BufferUnderflowException

    1.概述 写这个主要是遇到了这个问题,然后去研究一下,参考了几个大牛的文章. 首先遇到的错误如下 Exception in thread "main" java.nio.Buffe ...

  2. JAVA NIO是什么(zz)

    JAVA NIO是什么? 1.   基本 概念 IO 是主存和外部设备 ( 硬盘.终端和网络等 ) 拷贝数据的过程. IO 是操作系统的底层功能实现,底层通过 I/O 指令进行完成. 所有语言运行时系 ...

  3. JAVA NIO 简介(转)

    1.   基本 概念 IO 是主存和外部设备 ( 硬盘.终端和网络等 ) 拷贝数据的过程. IO 是操作系统的底层功能实现,底层通过 I/O 指令进行完成. 所有语言运行时系统提供执行 I/O 较高级 ...

  4. NIO之ByteBuffer_NIO之网络IO_与ChannelNetty初窥门径

    NIO之ByteBuffer与Channel 传统IO:byte[] <= inputStream <= 文件 => outputStream => byte[] NIO:文件 ...

  5. 网页怎么预先加载模型_修补预先训练的语言模型

    网页怎么预先加载模型 Can you fill in the words that I've removed from a recent announcement? 您能填写我从最近的公告中删除的词吗 ...

  6. 集合类 Java中的集合类解析和一些有深入的面试题

    Java集合类解析 List.Map.Set三个接口,存取元素时,各有什么特点? List 以特定次序来持有元素,可有重复元素.Set 无法拥有重复元素,内部排序.Map 保存key-value值,v ...

  7. java noi和io

    转载:http://www.iteye.com/topic/834447 1.   基本 概念 IO 是主存和外部设备 ( 硬盘.终端和网络等 ) 拷贝数据的过程. IO 是操作系统的底层功能实现,底 ...

  8. 面试要谈的计算机网络

    参照https://www.cnblogs.com/weijie4611/p/10769247.html 1.tcp和udp的区别  TCP:是面向连接的流传输控制协议,具有高可靠性,确保传输数据的正 ...

  9. 说说java NIO的一些个人总结

    首先了解下所谓的java nio是个什么东西! IO是靠字符或字节进行传输,比较慢! 而NIO是靠块, 也就相当于一个Buffer, 一块一块 的传输, 速度较快 ! 同时加入了多线程 的控制, 一个 ...

最新文章

  1. DDD-EF-数据仓储
  2. 从零开始学Win32平台缓冲区溢出(Part1)
  3. 比较简单的c语言编辑器,大佬们,小菜鸟想问一问用vc编译器做简易画图软件
  4. Hadoop Hive 创建表及count/distinct操作(会被翻译成mr程序)
  5. Spring JdbcTemplate CRUD增删改查操作
  6. java出现errors是什么错误_java中错误(error)和异常(exception)有什么主要区别?
  7. python中遇到循环import即circular import的问题原理剖析及解决方案
  8. deeply understanding Binary tree--二叉树
  9. UVa10006 Carmichael Numbers【素数判定+快速模幂】
  10. 大华存储服务器系统,大华重磅推出64盘位网络视频存储服务器
  11. 机器人视觉手眼标定学习笔记
  12. CMSIS应用于研究指南图文教程
  13. 中兴捧月比赛2020
  14. fatal: unable to connect to gitlab.domian: gitlab.domian : Temporary failure in name resolution
  15. 港科夜闻|香港科技大学校长叶玉如教授,新加坡国立大学曾运雄博士:发现阿尔茨海默病新疗法...
  16. 计算球体积和球表面积
  17. Java---鼠标事件小实例
  18. Matlab中实现圆形矩阵,圆外为0
  19. C6678里的汇编语言,TMS320C6678
  20. 《将博客搬至CSDN》_se7en3_新浪博客

热门文章

  1. 自己拥有一台服务器可以做哪些很酷的事情?
  2. java set 删除_Java Set remove()用法及代码示例
  3. 离散实验一 油管铺设 (求最小生成树的Prim算法的实际应用)
  4. 无效的月份oracle,Oracle插入失败:无效的月份
  5. 元宇宙之经济(01)理解区块链
  6. Unity 打包IOS平台错误
  7. 英语Catarinite天铁托甲catarinite镍铁陨石
  8. skimage.filters.frangi函数
  9. 怎样批量解析手机端头条视频和封面图片并保存
  10. 如何在比赛和项目中培养一个好的探索性分析(EDA)思维 —— 翻译自kaggle一位有趣的分享者