1、 概念介绍

缓冲区(Buffer)就是在内存中预留指定大小的存储空间用来对I/O的数据做临时存储,这部分预留的内存空间叫缓冲区。

使用缓冲区有两个好处:
1、减少实际物理读写次数
2、缓冲区在创建时就被分配内存,这块内存区域一直被重用,可以减少动态分配和回收内存的次数

一般在实际过程中,我们一般是先将文件读入内存,再从内存写入到别的地方,这样在输入输出过程中我们都可以用缓存来提升IO性能。

在java nio中,缓冲区的作用也是用来临时存储数据,可以理解为是I/O操作中数据的中转站。缓冲区直接为通道(channel)服务,写入数据到通道或从通道读取数据,这样利用缓冲区数据来传递就可以达到对数据高效处理的目的。在nio中主要有八种缓冲区类(其中MappedByteBuffer是专门用于内存映射的一种ByteBuffer):
ByteBuffer,CharBuffer,ShortBuffer,IntBuffer,LongBuffer,FloatBuffer,DoubleBuffer

2、Fields

所有缓冲区都有4个属性:capacity、limit、position、mark,并遵循mark<=position<=limit<=capacity,下表时对这4个属性的解释:

字段 作用
position 当前读到的位置
limit 当前写到的位置
capacity 容量
mark 标记,调用mark()来设置mark=position,在调用reset()可以让position恢复到标记位置

我写了这几个方法的测试方法,大家可以运行起来理解:

public static void main(String[] args) {System.out.println("---------test allocate ------------");System.out.println("before allocate:"+Runtime.getRuntime().freeMemory());//如果分配的内存过小,大小不会变化,要超过多少jvm才能感觉到?ByteBuffer buffer=ByteBuffer.allocate(102400);System.out.println("buffer = "+buffer);System.out.println("after allocate:"+Runtime.getRuntime().freeMemory());//这部分直接用的系统内存,所以对jvm的内存没有影响ByteBuffer directBuffer=ByteBuffer.allocateDirect(102400);System.out.println("directBuffer = "+directBuffer);System.out.println("after allocate:"+Runtime.getRuntime().freeMemory());System.out.println("----------  test wrap ---------");byte[]bytes=new byte[32];buffer=ByteBuffer.wrap(bytes);System.out.println(buffer);buffer=ByteBuffer.wrap(bytes,10,10);System.out.println(buffer);}

3、另外一些常用的方法

方法 描述
limit(),limit(10) 前者get,后者set
reset() 把position设置成mark的值
clear() position=0,limit=capacity,mark=-1
flip() limit=position,position=0,mark=-1;将缓冲区状态由存数据变为准备取数据
rewind() 把position设为0,mark设为-1,不改变limit的值
remaining() return limit-position
hasRemaining() return position < limit,是否还有未读内容
compact 把position到limit间的内容移到0到limit间,position和limit的取值分别变为limit-position、capacity;
也即将未读的内容拷贝到缓冲区开头,现在buffer准备好写数据,但是不会覆盖未读的数据;
如果先将position设置到limit,再compact,那么相当于clear
get() 相对读,从position读取一个byte,并将position+1,为下次读写做准备
get(int index) 绝对读,读取byteBuffer底层bytes下标为index的byte,不改变position
get(byte[]dst,int offset,int length) 从position开始相对读,读length个byte,并写入dst下标从offset到offset+length的区域
put(byte b) 相对写,向position写入一个byte,并将position+1,为下次读写做准备
put(int index,byte b) 绝对写,想byteBuffer底层的bytes中下标为index的位置插入byte b,不改变position
put(ByteBuffer src) 用相对写,把src中可读的部分(position-limit)写入到此byteBuffer)
put(byte[]src,int offset,int length 将src数组中offset到offset+length的数据写入到position之后,并将position+length

以下是这些方法的测试代码:

 public static void main(String[] args) {byte[]bytes=new byte[32];ByteBuffer buffer=ByteBuffer.wrap(bytes);System.out.println(buffer);buffer=ByteBuffer.wrap(bytes,10,10);System.out.println("----------Test reset -----------");buffer.clear();buffer.position(5);buffer.mark();buffer.position(10);System.out.println("before reset:"+buffer);buffer.reset();System.out.println("after reset:"+buffer);System.out.println("----------Test rewind -----------");buffer.clear();buffer.position(10);buffer.limit(15);System.out.println("before rewind:"+buffer);buffer.rewind();System.out.println("after rewind:"+buffer);System.out.println("----------Test compact -----------");buffer.clear();buffer.put("abcd".getBytes());System.out.println("before compact:"+buffer);System.out.println(new String(buffer.array()));buffer.flip();System.out.println("after flip:"+buffer);System.out.println((char)buffer.get());System.out.println((char)buffer.get());System.out.println((char)buffer.get());System.out.println("after three gets:"+buffer);System.out.println("\t"+new String(buffer.array()));buffer.compact();System.out.println("after compact:"+buffer);System.out.println("\t"+new String(buffer.array()));System.out.println("----------Test get -----------");buffer=ByteBuffer.allocate(32);buffer.put((byte)'a').put((byte) 'b').put((byte)'c').put((byte)'d').put((byte)'e').put((byte)'f');System.out.println("before flip:"+buffer);//转换为读取模式buffer.flip();System.out.println("before get:"+buffer);System.out.println((char)buffer.get());System.out.println("after get:"+buffer);//get(index)不影响positionSystem.out.println((char)buffer.get(2));System.out.println("after get(index):"+buffer);byte[]dst=new byte[10];buffer.get(dst,0,2);System.out.println("after get(dst,0,2):"+buffer);System.out.println("\t dst:"+new String(dst));System.out.println("buffer now is:"+buffer);System.out.println("\t"+new String(buffer.array()));System.out.println("----------Test put -----------");ByteBuffer bb=ByteBuffer.allocate(32);System.out.println("before put(byte):"+bb);System.out.println("after put(byte):" + bb.put((byte) 'z'));System.out.println("after put(2,(byte)'c'):"+ bb.put(2, (byte) 'c'));System.out.println("\t"+new String(bb.array()));//这里的buffer是abcdef[pos=3 limit=6 cap=32]bb.put(buffer);System.out.println("after put(buffer):"+bb);System.out.println("\t"+new String(bb.array()));}

缓冲区(Buffer)相关推荐

  1. 【Netty】NIO 选择器 ( Selector ) 通道 ( Channel ) 缓冲区 ( Buffer ) 网络通信案例

    文章目录 I . NIO 通信 服务器端 流程说明 II . NIO 通信 服务器端代码 III . NIO 通信 客户端 流程说明 IV . NIO 通信 客户端代码 V . NIO 通信 示例运行 ...

  2. 【Netty】NIO 缓冲区 ( Buffer ) 分散 Scattering 与 聚合 Gathering 操作

    文章目录 I . 缓冲区 ( Buffer ) 分散 Scattering 与 聚合 Gathering 概念 II . 缓冲区 ( Buffer ) 分散 Scattering 与 聚合 Gathe ...

  3. 【Netty】NIO 缓冲区 ( Buffer ) ( 缓冲区读写类型 | 只读缓冲区 | 映射字节缓冲区 )

    文章目录 I . 缓冲区 ( Buffer ) 存取类型 II . 只读缓冲区 ( ReadOnlyBuffer ) III . 映射字节缓冲区 ( MappedByteBuffer ) I . 缓冲 ...

  4. 【Netty】NIO 缓冲区 ( Buffer ) 组件

    文章目录 I . NIO 三大核心组件 对应关系 II . 缓冲区 ( Buffer ) 类 III . 缓冲区 ( Buffer ) 机制 IV . 缓冲区 ( Buffer ) 机制 示例解析 V ...

  5. 【Netty】NIO 简介 ( NIO 模型 | NIO 三大组件 | 选择器 Selector | 通道 Channel | 缓冲区 Buffer | NIO 组件分配 | 缓冲区示例 )

    文章目录 I . NIO 模型 II . NIO 三大组件交互流程 III . NIO 缓冲区 IV . NIO 与 BIO 对比 V . NIO 线程分配 VI . 缓冲区 ( Buffer ) 示 ...

  6. Java NIO3:缓冲区Buffer

    在上一篇中,我们介绍了NIO中的两个核心对象:缓冲区和通道,在谈到缓冲区时,我们说缓冲区对象本质上是一个数组,但它其实是一个特殊的数组,缓冲区对象内置了一些机制,能够跟踪和记录缓冲区的状态变化情况,如 ...

  7. muduo网络库学习(六)缓冲区Buffer及TcpConnection的读写操作

    在tcp的通信过程中,内核其实为tcp维护着一个缓冲区 当调用write/send时,会向内核缓冲区中写入数据,内核和tcp协议栈负责将缓冲区中的数据发送到指定<ip,port>的目标位置 ...

  8. Java NIO_I/O基本概念_Java中的缓冲区(Buffer)_通道(Channel)_网络I/O

    I/O基本概念 缓冲区基础 缓冲区是I/O的基础, 进程使用read(), write()将数据读出/写入从缓冲区中; 当缓冲区写满, 内核向磁盘发出指令, 将缓冲区中数据写入磁盘中(这一步不需要CP ...

  9. Java NIO学习篇之缓冲区Buffer详解

    定义 缓冲区Buffer在java nio中负责数据的存储,缓冲区就是数组,用于存储不同类型数据的数组. jdk为java七大基本类型数据都准备了响应的缓冲区(boolean值除外): ByteBuf ...

  10. NIO(一)——缓冲区Buffer

                                        NIO(一)--Buffer NIO简介 NIO即New IO,是用来代替标准IO的,提供了与标准IO完全不同传输方式. 核心: ...

最新文章

  1. 微信内测附近的餐厅,小程序要跨界外卖了?
  2. SQL Server通过动态视图里查找阻塞超过30秒的会话
  3. Ocelot 集成Butterfly 实现分布式跟踪
  4. 实现定时中断_无线传感器网络实验报告(二)Timer定时应用实验
  5. Python __subclasses__() 函数获取类的所有子类
  6. 7个习惯可以改变一个人和他的一生
  7. 1TB存储版iPhone 13 Pro机型预计交付时间已被推迟至10月
  8. 彩色人物创意灵感|C4D万物皆可造!
  9. python qt信号在qml 的使用_Python和C++混合使用QML开发GUI
  10. PayPal网站付款标准版(for PHP)
  11. if(!!boolean)两次取反
  12. 保持长宽比 对背景图像进行修改android:scaleType=fitXY
  13. 递归算法经典实例python-Python递归算法详解
  14. Android 读取按键及Touch Panel
  15. CSM会议室预约系统源码
  16. ArcCatalog不能预览地图服务
  17. 微信公众号配置模板消息
  18. PECompact 2.79 Beta D by Sonny27
  19. swift锁屏播放,音乐进度更新,专辑,歌手名显示
  20. [裴礼文数学分析中的典型问题与方法习题参考解答]5.1.4

热门文章

  1. Verilog——JTAG标准的状态机实现
  2. schmitt trigger 施密特触发器 【数字电路】
  3. 操作系统实验--进程间通信
  4. linux自动备份数据库并发送邮件
  5. registerReceiver 动态注册与 sendBroadcast 源码解析
  6. STM32驱动1602A 8086协议
  7. 2022年G2电站锅炉司炉理论题库及在线模拟考试
  8. Windows开启administrator账户
  9. CATIA操作经典技巧问答
  10. Cassandra代替Redis?