JAVANIOBuffer中各种重要的状态属性的含义与关系图解
一个简单的NIO例子
FileOutputStream outputStream = new FileOutputStream("NioTest3.txt");
FileChannel channel = outputStream.getChannel();
//穿件一个512 大小的buffer
ByteBuffer byteBuffer = ByteBuffer.allocate(512);
byte[] bytes = "hello wolr jian geg wo ai ni ".getBytes();
for (int i = 0; i < bytes.length; i++) {
byteBuffer.put(bytes[i]);
}
byteBuffer.flip();
channel.write(byteBuffer);
outputStream.close();
}
//这个方法是我们在NIO中必须要用到的东西
//读写切换必须要用方法 ,写数据 状态的翻转读写的切换
byteBuffer.flip();
NIO的基本概念与笔记
Io中最核心的一个概念为流(Stream),面向流的编程,是信息的载体。通过流获取到相关信息,要么是输入流 ,要么是输出流,一个流要么是输入流, 要么是输出流 不可同时既是输入流,又是输出流 直接读
在NIo中 3个概念 Selector选择器, Channel ,Buffer 在nio 中我们是面向block 块 和面向buffer 缓冲的 buffer本身就是一块内存 底层实现上就是一个数组,数据的读和谐都是操作数组来实现的,一个缓冲区既可以读和写 先读到buffer 中 也可以写到buffer 中,不仅可以读还可以写 @flip 方法 切换读写的状态的
除了数组之外,buffer 还一共了对于数据的结构化访问方式,并且可以追踪到系统的读写过程
Java 中8中原声数据类型都由各自对应这buffer 类型 int char bytybuffer
示意图:一个线程对用这一个Selector 一个selector 对应3个channel一个channel 对应这一个buffer
一个线程可以在这三个channel上面来回切换, 具体某一个时刻切换到哪儿 是由event 来决定的 event 通过event来判断当前selector 在哪儿
Event 时间的判断 NIO 里面的Channel 可以理解为IO 中的Stream
Buffer 本身就是一块内存,底层实现上 它实际上就是一个数组
数据的读与写都是通过 BUffer来操作的 数据的读与写都是Buffer来操作的
FileChannel 数据从Channel读取到Buffer里面 在读取到程序中
Channel是双向的所以他能更好的反映出底层操作系统的真实情况
源码看一看大概的意思与 问题 :buffer是怎么读?怎么写?flip()方法执行的原理:
那么它的原理是什么样子的呢?源码分析 :
关于NIO BUffer中的重要的三个属性的含义 :postiton,limit与capacity
在JavaDoc里面有这么一句话
Aside from its content, the essential properties of a
* buffer are its capacity, limit, and position:(buffer的本质就是capacity,limit,和position)
* capacity容量,position限制,limit位置
capacity 也就是我们初始化的大小,它不会改变 分配好之后就永远不会改变 ByteBuffer.allocate(512); 这样里面就是capacity大小就是512
<p> A buffer's <i>capacity</i> is the number of elements it contains. The
* capacity of a buffer is never negative and never changes. </p>
*
* <p> A buffer's <i>limit</i> is the index of the first element that should
* not be read or written. A buffer's limit is never negative and is never
* greater than its capacity. </p>
*
* <p> A buffer's <i>position</i> is the index of the next element to be
* read or written. A buffer's position is never negative and is never
* greater than its limit. </p>
如图: 我们创建一个大小为6的buffer 那么它得 capacity 也就是为 6
因为我们的索引是从0开始的 所以 它得capacity 值也就指向了最后一个元素的下一个元素
那么它的limit 也是指向了 6
大致过程:
p代表position ,
Buffer类简单了解
Buffer的类型
direct buffers 创建在堆中的内存,拷贝的时候实现方式是0拷贝的,直接缓存
一种是普通的Buffer
代码测试
public static void main(String[] args) {
//将整数生成一个并且随机的
IntBuffer buffer = IntBuffer.allocate(10);
for (int i = 0; i < 5; ++i) {
//生成一个随机数
int randomNumber = new SecureRandom().nextInt(20);
buffer.put(randomNumber);
}
//输出 10
System.out.println("before flip limit" + buffer.limit());
//写数据 状态的翻转读写的切换
buffer.flip();
//翻转完之后的打印
System.out.println("after flip limit" + buffer.limit());
//读数据
while (buffer.hasRemaining()) {
System.out.println("position" + buffer.position());
System.out.println("limit" + buffer.limit());
System.out.println("capacity" + buffer.capacity());
System.out.println(buffer.get());
}
}
result
before flip limit10
after flip limit5
进入到While循环.....
position0
limit5
capacity10
获取到的随机数:12
position1
limit5
capacity10
获取到的随机数:1
position2
limit5
capacity10
获取到的随机数:8
position3
limit5
capacity10
获取到的随机数:4
position4
limit5
capacity10
获取到的随机数:0
Process finished with exit code 0
结果分析参照画的图图
操作File文件的示例
public static void main(String[] args) throws Exception {
FileInputStream inputStream = new FileInputStream("input.txt");
FileOutputStream outputStream = new FileOutputStream("output.txt");
FileChannel inputChannel = inputStream.getChannel();
FileChannel outputChannel = outputStream.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(512);
while (true) {
//这个Clear 方法必须添加 要不然它会一直写文件到Out.txt中
buffer.clear();
int read = inputChannel.read(buffer);
System.out.println("read ::" + read);
if (-1 == read) {
break;
}
buffer.flip();
outputChannel.write(buffer);
}
inputChannel.close();
outputChannel.close();
}