基本介绍

缓冲区(Buffer):缓冲区本质上是一个可以读写数据的内存块,可以理解成是一个容器对象(含数组),该对象提供了一组方法,可以更轻松地使用内存块,缓冲区对象内置了一些机智,能够跟踪和记录缓冲区的状态变化情况。Channel提供从文件、网络读取数据的渠道,但是读取或写入的数据都必须经由Buffer

Buffer类及其子类

1.在NIO中,Buffer是一个顶层父类,它是一个抽象类,类的层级关系图:

常用Buffer子类一览

  1. ByteBuffer,存储字节数据到缓冲区
  2. ShortBuffer,存储字符串数据到缓冲区
  3. CharBuffer,存储字符数据到缓冲区
  4. IntBuffer,存储整数数据到缓冲区
  5. LongBuffer,存储长整型数据到缓冲区
  6. DoubleBuffer,存储小数到缓冲区
  7. FloateBuffer,存储小数到缓冲区

2.Buffer类定义了所有的缓冲区都具有的四个属性来提供关于其所包含的数据元素的信息


属性 描述
Capacity 容量,既可以容纳的最大数据量;在缓冲区创建时被设定并且不能改变
Limit 便是缓冲区的当前终点,不能对缓冲区超过极限的位置进行读写操作。且极限是可以修改的
Position 位置,下一个要被读或写的元素的索引,每次读写缓冲区数据时都会改变该值,为下次读写作准备
Mark 标记,调用mark()来设置mark=position,再调用reset()可以让position恢复到标记的位置

3.Buffer类相关方法一览

ByteBuffer
从前面可以看出对于java中的基本数据类型(boolean除外),都有一个Buffer类型与之相对应,最常用的自然是ByteBuffer类(二进制数据),该类的主要方法如下:

Buffer简单使用

debug运行,查看buffer属性值的变化

package com.example.demo.netty;import java.nio.IntBuffer;public class BasicBuffer {public static void main(String[] args) {//举例说明Buffer的使用(简单说明)//创建一个Buffer,大小为5,既可以存放5个intIntBuffer intBuffer = IntBuffer.allocate(5);//向Buufer存放数据
//        intBuffer.put(10);
//        intBuffer.put(11);
//        intBuffer.put(12);
//        intBuffer.put(13);
//        intBuffer.put(14);for (int i = 0; i < intBuffer.capacity(); i++) {intBuffer.put( i * 2);}//如何从buffer读取数据//将buffer转换,读写切换intBuffer.flip();while (intBuffer.hasRemaining()) {System.out.println(intBuffer.get());}}
}

查看flip()方法做了什么

 public final Buffer flip() {limit = position;position = 0;mark = -1;return this;}

关于Buffer和Channel的注意事项和细节

  1. ByteBuffer支持类型化的put和get,put放入的是什么数据类型,get就应该使用相应的数据类型来取出,否则可能有BufferUnderflowException异常
  2. 可以将一个普通Buffer转化成只读Buffer
  3. NIO还提供了MappedByteBuffer,可以让文件直接在内存(堆外的内存)中进行修改,而如何同步到文件由NIO来完成
  4. 前面我们讲的读写操组,都是通过一个Buffer完成的,NIO还支持通过多个Buffer(即Buffer数组)完成读写操作,即Scattering和Gatering

demo1

package com.example.demo.netty;import java.nio.ByteBuffer;/*** ByteBuffer 支持类型化的 put 和 get,put 放入的是什么数据类型,get 就应该使用相应的数据类型来取出,否则可能有 BufferUnderflowException 异常*/
public class NIOByteBufferPutGet {public static void main(String[] args) {// 创建一个 BufferByteBuffer buffer = ByteBuffer.allocate(64);// 类型化方式放入数据buffer.putInt(100);buffer.putLong(9L);buffer.putChar('我');buffer.putShort((short) 4);// 读取数据buffer.flip();System.out.println("----------");System.out.println(buffer.getInt());System.out.println(buffer.getLong());System.out.println(buffer.getChar());System.out.println(buffer.getShort());}
}

demo2

package com.example.demo.netty;import java.nio.ByteBuffer;/*** 可以将一个普通Buffer转化成只读Buffer*/
public class ReadOnlyBuffer {public static void main(String[] args) {//创建一个bufferByteBuffer buffer = ByteBuffer.allocate(64);for (int i = 0; i < 64; i++) {buffer.put((byte) i);}//读取buffer.flip();//得到一个只读的bufferByteBuffer readOnlyBuffer = buffer.asReadOnlyBuffer();System.out.println(readOnlyBuffer.getClass());//读取while (readOnlyBuffer.hasRemaining()) {System.out.println(readOnlyBuffer.get());}readOnlyBuffer.put((byte) 100); // ReadOnlyBufferException}
}

demo3

package com.example.demo.netty;import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;/*** 说明* MappedByteBuffer 可以让文件直接在内存(堆外内存)修改,操作系统不需要拷贝一次*/
public class MappedByteBufferTest {public static void main(String[] args) throws Exception {RandomAccessFile randomAccessFile = new RandomAccessFile("1.txt", "rw");//获取对应的通道FileChannel channel = randomAccessFile.getChannel();/*** 参数1:FileChannel.MapMode.READ_WRITE 使用的读写模式* 参数2: 0:可以直接修改的起始位置* 参数3: 5:是映射到内存的大小,即将1.txt的多少个字节映射到内存* 可以直接修改的范围就是0-5*/MappedByteBuffer mappedByteBuffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, 5);mappedByteBuffer.put(0, (byte) 'H');mappedByteBuffer.put(3, (byte) '9');//        mappedByteBuffer.put(5, (byte) 'Y');//IndexOutOfBoundsExceptionrandomAccessFile.close();}
}

demo4

package com.example.demo.netty;import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Arrays;/*** Scattering: 将数据写入到buffer时,可以采用buffer数组,依次写入(分散)* Gathering: 从buffer读取数据时,可以采用buffer数组,依次读*/
public class ScatteringAndGatheringTest {public static void main(String[] args) throws Exception {// 使用 ServerSocketChannel 和 ServerSocketChannel 网络ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();InetSocketAddress inetSocketAddress = new InetSocketAddress(7000);// 绑定端口到socket,并启动serverSocketChannel.socket().bind(inetSocketAddress);// 创建buffer数组ByteBuffer[] byteBuffers = new ByteBuffer[2];byteBuffers[0] = ByteBuffer.allocate(5);byteBuffers[1] = ByteBuffer.allocate(3);// 等客户端连接(telnet)SocketChannel socketChannel = serverSocketChannel.accept();int msgLen = 8; // 假定从客户端接收8个字符while (true) {int byteRead = 0;while (byteRead < msgLen) {long l = socketChannel.read(byteBuffers);byteRead += l; //累计读取的字节数System.out.println("byteRead=" + byteRead);Arrays.asList(byteBuffers).stream().map(buffer -> "postion=" + buffer.position() + ",limit=" + buffer.limit()).forEach(System.out::println);}// 将所有的buffer进行flipArrays.asList(byteBuffers).forEach(buffer -> buffer.flip());// 将数据读出显示到客户端long byteWrite = 0;while (byteWrite < msgLen) {long l = socketChannel.write(byteBuffers);byteWrite += l;}// 将所有的buffer 进行clearArrays.asList(byteBuffers).forEach(buffer -> buffer.clear());System.out.println("byteRead:=" + byteRead + " byteWrite=" + byteWrite + ",messageLenth=" + msgLen);}}
}

(四)Netty之Buffer缓冲区相关推荐

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

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

  2. Java NIO ———— Buffer 缓冲区详解

    引言 缓冲区是一个用于特定基本类型的容器.由java.nio 包定义,所有缓冲区都是 Buffer 抽象类的子类. Java NIO 中的 Buffer ,主要用于与NIO 通道进行交互.数据从通道存 ...

  3. node事件循环 EventEmitter 异步I/O Buffer缓冲区 模块

    node.js事件循环 node.js单进程,单线程的程序 每一个api都支持回调 所有的事件机制都是设计模式中的 一共是23种设计模式 http://design-patterns.readthed ...

  4. node事件循环 EventEmitter 异步I/O Buffer缓冲区 模块

    node.js事件循环 node.js单进程,单线程的程序 每一个api都支持回调 所有的事件机制都是设计模式中的 一共是23种设计模式 http://design-patterns.readthed ...

  5. JAVA NIO:NIO与OIO的对比以及Channel通道、Selector选择器、Buffer缓冲区的介绍 高并发

    文章目录 二 Java NIO (一)NIO对比OIO (二)概述三个核心组件 Channel通道 Selector选择器 Buffer缓冲区 (三)Buffer详解 1 Buffer类 2 四个属性 ...

  6. JAVA NIO:NIO与OIO的对比以及Channel通道、Selector选择器、Buffer缓冲区的介绍 //高并发

    文章目录 二 Java NIO (一)NIO对比OIO (二)概述三个核心组件 Channel通道 Selector选择器 Buffer缓冲区 (三)Buffer详解 1 Buffer类 2 四个属性 ...

  7. Node.js Buffer(缓冲区)

    一.Node.js Buffer(缓冲区) JavaScript 语言自身只有字符串数据类型,没有二进制数据类型. 但在处理像TCP流或文件流时,必须使用到二进制数据.因此在 Node.js中,定义了 ...

  8. 95-50-040-java.nio.channels-NIO-NIO之Buffer(缓冲区)

    1.世界 Java NIO之Buffer(缓冲区) Buffer(缓冲区)介绍 Java NIO Buffers用于和NIO Channel交互. 我们从Channel中读取数据到buffers里,从 ...

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

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

最新文章

  1. 华为--PPP典型配置举例
  2. c语言太极图编程语言,利用C语言的Cairo图形库绘制太极图实例教程.pdf
  3. python编程入门指南怎么样-如果想学python怎么入门?
  4. 编程之美系列之二——寻找出现频率超过一半的数
  5. php 连续点击事件,javascript设置连续两次点击按钮时间间隔的方法_javascript技巧...
  6. c语言主函数如何获得子函数的值,子函数中的数组值怎么带回主函数中?
  7. BZOJ 3404: [Usaco2009 Open]Cow Digit Game又见数字游戏(博弈论)
  8. [Perforce系列—] 1. 使用Perforce 命令 与常用命令
  9. pjlib深入剖析和使用详解
  10. Bailian2998 日志排序【排序】
  11. 力扣-102. 二叉树的层序遍历
  12. 关于Request.params的知识收藏
  13. 三容水箱液位控制系统_基于Labview软件编程的三容水箱液位控制系统
  14. 入学人数突破1000人! 阿里云大学云学院,开启创新育才实践之路!
  15. ffmpeg -比特率,帧率和文件大小
  16. 元器件采购系统的主要功能,数字化采购助力元器件企业飞速发展
  17. android 使用epublib开源框架解析epub文件(章节内容、书籍菜单)
  18. 重庆大学计算机学院课题组,【计算机】计算机学院关于智能计算的大规模优化学术报告圆满结束...
  19. 同步消息和异步消息的区别
  20. PDF转换成word免费

热门文章

  1. python初学者用什么软件_初学者编写python用什么软件
  2. 程序员表白代码python_程序员python表白代码
  3. 在unity向量空间内绘制几何(2):计算球体的表面坐标
  4. Android:进度条加载
  5. 高斯拟合 vc++代码_使用python+sklearn实现核岭回归和高斯回归的比较
  6. SQL left join 、right join 、inner join
  7. MySQL数据库 --基础
  8. TensorFlow基础笔记(13) tf.name_scope tf.variable_scope学习
  9. c++中字符输入函数getline、cin.getline区分
  10. C语言之程序中内存的来源:栈 堆 数据段