盘一盘 NIO (一)—— Buffer源码解析
2024-09-08 13:57:16
Buffer是个啥?
Buffer 即缓冲区,用来暂存输入输出数据的区域。Buffer对象是一份固定数量的数据的容器,实质上是一个数组。但是一个缓冲区不仅仅是一个数组,缓冲区提供了对数据的结构化访问,还可以跟踪系统的读/写进程。
在 Java传统 IO 中,数据直接写入或者将数据直接读到 Stream 对象中。
而在 NIO 中,所有数据都是用缓冲区处理的。在读取数据时,它是直接读到缓冲区中的。在写入数据时,它是写入到缓冲区中的。任何时候访问 NIO 中的数据,都是将它放到缓冲区中。
NIO中的Buffer主要用于与NIO通道(channel)进行交互,数据是从通道读入缓冲区,从缓冲区写入通道中的。
继承关系图
Buffer作为一个容器用来存储数据的,根据存储数据类型的不同,分为以下七种:
ByteBuffer,CharBuffer,ShortBuffer,IntBuffer,LongBuffer,FloatBuffer,DoubleBuffer
主要属性
// 标记、位置、限制、容量遵守以下不变式:
// 0<=mark<=position<=limit<=capacity // 标记是一个位置索引,可以在之后设置位置为标记值再次读写。
private int mark = -1; // 位置,表示缓冲区中正在操作数据的位置。
// 可以把position理解成一个指针,指向的位置就是操作的位置。
private int position = 0; // 界限,表示缓冲区中可以操作数据的大小。
private int limit; // 容量,表示缓冲区中最大存储数据的容量。一旦声明,不可改变。
private int capacity; // 指向缓冲区的地址
long address;
构造方法
// 创建一个具有给定标记、位置、限制和容量的新缓冲区
Buffer(int mark, int pos, int lim, int cap) {
// 缓冲区的初始化容量不能小于0
if (cap < 0)
throw new IllegalArgumentException("Negative capacity: " + cap);
// 初始化缓冲区容量
this.capacity = cap;
// 初始化缓冲区限制,设置最新的缓冲区Buffer
limit(lim);
position(pos);
if (mark >= 0) {
if (mark > pos)
throw new IllegalArgumentException("mark > position: ("
+ mark + " > " + pos + ")");
this.mark = mark;
}
}
关键方法解析
position方法:设置当前操作位置
public final Buffer position(int newPosition) {
// 当前操作位置不能超过limit大小,不能小于0
if ((newPosition > limit) || (newPosition < 0))
throw new IllegalArgumentException();
position = newPosition;
// 如果标记位置大于正在操作位置,那么将mark设置为-1。
if (mark > position) mark = -1;
return this;
}
limit方法:设置缓冲区限制
public final Buffer limit(int newLimit) {
// newLimit大小不能超过缓冲区最大容量capacity,不能小于0
if ((newLimit > capacity) || (newLimit < 0))
throw new IllegalArgumentException();
limit = newLimit;
// 正在操作数据的位置不能大于界限
if (position > limit) position = limit;
// 如果标记位置大于界限,那么将mark设置为-1。
if (mark > limit) mark = -1;
return this;
}
reset方法:将缓冲区Buffer的位置position设置为以前临时备忘变量mark存储的位置
public final Buffer reset() {
int m = mark;
if (m < 0)
throw new InvalidMarkException();
position = m;
return this;
}
clear方法:清除缓冲区,clear方法并没有将之前的数据真的清除,当读数据前调用flip方法后,limit会限制不让使用旧数据。
public final Buffer clear() {
position = 0;
// 虽然将limit数值设置为最大容量,只是为了正常使用buffer
limit = capacity;
mark = -1;
return this;
}
flip方法: 反转此缓冲区,在进行写完去读的时候使用,说白了,让你开始读的时候从初始位置0开始。
public final Buffer flip() {
// 将position置为0,其实就是切换读写模式
limit = position;
position = 0;
mark = -1;
return this;
}
rewind方法:重绕此缓冲区,在通道写入或者获取之前调用
public final Buffer rewind() {
position = 0;
mark = -1;
return this;
}
remaining方法:返回当前的缓冲区Buffer中剩余元素的数量
public final int remaining() {
return limit - position;
}
总结
1、Buffer中所有的方法操作,都遵守以下不变式:
0<=mark<=position<=limit<=capacity
2、flip方法,让数据开始读的时候从初始位置0开始。
3、clear方法其实是个障眼法,并没有清除之前数据内容。
最新文章
- iOS学习19之OC类的扩展
- com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException: Invalid byte 2 of 2-byte
- python语法笔记(三)
- setcookie 之 我见
- Struts2中的session、request、respsonse获取方法
- 使用Idea编写javaweb以及maven的综合(一)
- 一套代码小程序&;Web&;Native运行的探索05——snabbdom
- Chrome 禁止从页面打开 Data URI 网址了
- Expm 10_2 实现Ford-Fulkerson算法,求出给定图中从源点s到汇点t的最大流,并输出最小割。
- 47_并发编程-线程python实现
- JavaEE编程实验 实验1 Java常用工具类编程(未完成)
- Exception的妙用
- 【转】Visual Studio团队资源管理器 Git 源码管理工具简单入门
- JAVA序列化和反序列化 对象<;=>;IO流 对象<;=>;字节数组
- ubuntu查找命令比较
- 解释mysql 语句 ——解释CREATE DATABASE `test` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci
- PAT 1001 Format
- thinkphp5中Indirect modification of overloaded element of XXX has no effect的解决办法
- Spring Data JPA 基本使用
- rails 中 create, new, build, save 的用法以及误区汇总 (转)