Java NIO技术学习之二
来源:互联网 发布:unity3d游戏大全 编辑:程序博客网 时间:2024/06/07 07:03
在上一篇中,我们介绍了NIO中的两个核心对象:缓冲区和通道。本文为NIO入门学习的第二篇,将会分析NIO中的缓冲区Buffer的内部原理。
在谈到缓冲区时,我们说缓冲区对象本质上是一个数组,但它其实是一个特殊的数组,缓冲区对象内置了一些机制,能够跟踪和记录缓冲区的状态变化情况,如果我们使用get()方法从缓冲区获取数据或者使用put()方法把数据写入缓冲区,都会引起缓冲区状态的变化。
在缓冲区中,最重要的属性有下面三个,它们一起合作完成对缓冲区内部状态的变化跟踪:
position
指定了下一个将要被写入或者读取的元素索引。在从Channel读取数据到Buffer时,position变量用来跟踪截止目前为止从Channel中读出了多少数据,在从Buffer中向Channel写数据时,position变量用来跟踪截止目前为止向Channel写入了多少数据。
limit
在从Channel中读取数据到Buffer中时,limit变量指示了还剩多少空间可供存放数据,在从Buffer向Channel写数据时,limit变量指示了还剩多少数据可以写入。position正常情况下小于或者等于limit。
capacity
指示Buffer最多能够存储的数据。实际上,它指示了底层array的容量,或者至少是底层array允许使用的空间数量。Limit永远不会大于capacity。
接下来我们将逐一检查每个细节,并且也看看为什么这样的设计适合典型的读/写(输入/输出)处理。我们假设从一个Channel拷贝数据到另一个Channel。
首先新建一个容量大小为10的ByteBuffer对象,在初始化的时候,position设置为0,如果我们读一些数据到缓冲区中,那么下一个读取的数据就进入索引为0的字节。如果我们从缓冲区写一些数据,从缓冲区读取的下一个字节就来自索引为0的字节。limit和 capacity被设置为10,在以后使用ByteBuffer对象过程中,capacity的值不会再发生变化,而其它两个将会随着使用而变化。
现在我们可以从读通道中读取一些数据到缓冲区中。如果读取到4个字节数据,则此时position的值为4,即下一个将要被写入的字节索引为4,而limit仍然是10,如下图所示:
下一步把读取到的数据写入到写通道中,在此之前必须调用flip()方法,该方法将会完成两件事情:
1. 把limit设置为当前的position值
2. 把position设置为0
position 被设置为 0,这意味着我们得到的下一个字节是第一个字节。limit 已被设置为原来的 position,这意味着它包括以前读到的所有字节,并且一个字节也不多,如下图所示:
我们现在可以将数据从缓冲区写入通道了,这会导致position的增加而limit保持不变,但position不会超过limit的值,所以在读取我们之前写入到缓冲区中的4个字节之后,position和limit的值都为4,如下图所示:
在数据写入到写通道完毕后,调用clear()方法能够把所有的状态变化设置为初始化时的值,该方法将会完成两件事情:
1. 把limit设置为capacity值
2. 把position设置为0
clear()方法会重置Buffer以便接收更多的字节,如下图所示:
最后我们用一段代码来验证这个过程,如下所示:
import java.io.FileInputStream;import java.io.FileOutputStream;import java.nio.Buffer;import java.nio.ByteBuffer;import java.nio.channels.FileChannel;public class TestBufferField { public static void main(String[] args) throws Exception { FileInputStream fileInStream = new FileInputStream("D:\\test1.txt"); // 获取读通道 FileChannel fcin = fileInStream.getChannel(); FileOutputStream fileOutStream = new FileOutputStream("D:\\test2.txt"); // 获取写通道 FileChannel fcout = fileOutStream.getChannel(); // 创建缓冲区 ByteBuffer buffer = ByteBuffer.allocate(10); output("初始化", buffer); // 从通道fcin读取数据到缓冲区 fcin.read(buffer); output("调用read()", buffer); // 重设buffer,将limit设置为position,然后将position设置为0 buffer.flip(); output("调用flip()", buffer); // 将缓冲区中的数据写入通道fcout fcout.write(buffer); output("调用write()", buffer); // 重设buffer,将limit设置为容量capacity,position设置为0 buffer.clear(); output("调用clear()", buffer); fileInStream.close(); fileOutStream.close(); } public static void output(String step, Buffer buffer) { System.out.println(step + " : "); System.out.print("position: " + buffer.position() + ", "); System.out.print("limit: " + buffer.limit() + ", "); System.out.println("capacity: " + buffer.capacity()); System.out.println(); }}
输出结果为:
这与我们上面演示的过程一致。在后面的文章中,我们继续介绍NIO中关于缓冲区一些更高级的使用。
参考:
Java NIO使用及原理分析(二)
NIO 入门
- Java NIO技术学习之二
- Java NIO技术学习之三
- java nio 系列学习之二
- Java NIO学习二
- Java中NIO技术学习
- Java NIO技术学习之一
- Java之nio学习
- Java NIO学习笔记之二-图解ByteBuffer
- Java NIO学习笔记之二-图解ByteBuffer
- Java NIO学习笔记之二-图解ByteBuffer
- Java NIO学习笔记之二-图解ByteBuffer
- Java NIO 学习(二)
- java nio学习(二)
- Java NIO 学习(二)--Buffer
- Java NIO学习(二)
- java nio学习(二)
- java学习-NIO(二)Buffer
- Java 之NIO(二) - Channel
- JSP页面加入百度富文本框
- 2018网易校招前端开发工程师笔试卷讨论
- Maven2的配置文件settings.xml
- 工作感悟
- [Problem one]服务自启动导致无法找到动态库文件
- Java NIO技术学习之二
- 在java环境中使用sphinx搜索引擎
- swift 委托的用法
- 牛客网华为在线训练---取近似值
- response.setHeader()的用法
- spring boot admin系统监控处理
- ubuntu caffe安装
- Copy List with Random Pointer问题及解法
- Ubuntu系列 2:Ubuntu16.04 安装Windows字体