NIO浅析
来源:互联网 发布:网络企业资质怎么办理 编辑:程序博客网 时间:2024/06/06 14:00
1、NIO概述
java.nio是在jdk1.4中新引入的类库,nio是java new io的简称,其提供了高速的、面向块的 I/O,与面向流的io相比,面向块的操作明显比面向流的快许多,面向流的I/O系统一次一个字节或者一个字符的处理数据,输入流生产一个字节/字符的数据,输出流消耗一个字节/字符的数据,而面向块的I/O系统的处理则是每一个操作都在一步中产生或者消费一个数据块,所以按块处理数据比按(流式的)字节处理数据要快得多,NIO以通道Channel和缓冲区Buffer为基础来实现面向块的IO数据处理,通道和缓冲区是NIO中的核心对象,几乎在每一个I/O操作中都要使用它们。 通道Channel是对原I/O包中的流的模拟。到任何目的地(或来自任何地方)的所有数据都必须通过一个Channel对象。缓冲区Buffer实质上是一个容器对象。发送给一个通道的所有对象都必须首先放到缓冲区中;同样地,从通道中读取的任何数据都要读到缓冲区中。
2、NIO缓冲区
NIO 中两个重要的缓冲区组件:状态变量和访问方法 (accessor)。
状态变量:每一个读/写操作都会改变缓冲区的状态。通过记录和跟踪这些变化,缓冲区就可能够内部地管理自己的资源。从Buffer的源码中可以得到其定义了三个属性:
private int position = 0;private int limit;private int capacity;
可以根据这三个属性指定缓冲区在任意时刻的状态
1) position
缓冲区实际上就是美化了的数组。在从通道读取时,您将所读取的数据放到底层的数组中。 position
变量跟踪已经写了多少数据。更准确地说,它指定了下一个字节将放到数组的哪一个元素中。因此,如果您从通道中读三个字节到缓冲区中,那么缓冲区的position
将会设置为3,指向数组中第四个元素。
同样,在写入通道时,您是从缓冲区中获取数据。 position
值跟踪从缓冲区中获取了多少数据。更准确地说,它指定下一个字节来自数组的哪一个元素。因此如果从缓冲区写了5个字节到通道中,那么缓冲区的position
将被设置为5,指向数组的第六个元素。
2) limixt
limit
变量表明还有多少数据需要取出(在从缓冲区写入通道时),或者还有多少空间可以放入数据(在从通道读入缓冲区时)。
position
总是小于或者等于 limit
。
3)capacity
缓冲区的 capacity
表明可以储存在缓冲区中的最大数据容量。实际上,它指定了底层数组的大小 ― 或者至少是指定了准许我们使用的底层数组的容量。
limit
决不能大于 capacity
。
接下来我们看一下他们是如何协同工作的:
初始变量:
我们首先观察一个新创建的缓冲区,以ByteBuffer为例,假设缓冲区的大小为8个字节,ByteBuffer初始状态如下:
回想一下 ,limit决不能大于capacity,此例中这两个值都被设置为8。我们通过将它们指向数组的尾部之后(第8个槽位)来说明这点。
我们再将position设置为0。表示如果我们读一些数据到缓冲区中,那么下一个读取的数据就进入 slot 0。如果我们从缓冲区写一些数据,从缓冲区读取的下一个字节就来自slot 0。position设置如下所示:
由于缓冲区的最大数据容量capacity不会改变,所以我们在下面的讨论中可以忽略它。
第一次读取:
现在我们可以开始在新创建的缓冲区上进行读/写操作了。首先从输入通道中读一些数据到缓冲区中。第一次读取得到三个字节。它们被放到数组中从position开始的位置,这时position被设置为0。读完之后,position就增加到了3,如下所示,limit没有改变。
第二次读取:
在第二次读取时,我们从输入通道读取另外两个字节到缓冲区中。这两个字节储存在由position所指定的位置上, position因而增加2,limit没有改变。
flip:
现在我们要将数据写到输出通道中。在这之前,我们必须调用flip()方法。 其源代码如下:
public final Buffer flip() { limit = position; position = 0; mark = -1; return this;}
上一个图显示了在flip之前缓冲区的情况。下面是在flip之后的缓冲区:
我们现在可以将数据从缓冲区写入通道了。position被设置为0,这意味着我们得到的下一个字节是第一个字节。limit已被设置为原来的position,这意味着它包括以前读到的所有字节,并且一个字节也不多。
第一次写入:
在第一次写入时,我们从缓冲区中取四个字节并将它们 写入输出通道。这使得position增加到4,而limit不变,如下所示:
第二次写入:
我们只剩下一个字节可写了。limit在我们调用flip()时被设置为5,并且position不能超过limit。 所以最后一次写入操作从缓冲区取出一个字节并将它写入输出通道。这使得position增加到5,并保持limit不变,如下所示:
clear:
最后一步是调用缓冲区的clear()方法。这个方法重设缓冲区以便接收更多的字节。其源代码如下:
public final Buffer clear() { osition = 0; limit = capacity; mark = -1; return this;}
下面我们来看一个使用nio输入输出的例子:
/** * 将一个文件的所有内容拷贝到另一个文件中。 * * CopyFile.java 执行三个基本操作: * 首先创建一个 Buffer,然后从源文件中将数据读到这个缓冲区中,然后将缓冲区写入目标文件。 * 程序不断重复 — 读、写、读、写 — 直到源文件结束。 * * @version 1.00 2010-5-19, 10:49:46 * @since 1.5 * @author ZhangShixi */public class CopyFile { public static void main(String[] args) throws Exception { String infile = "C:\\copy.sql"; String outfile = "C:\\copy.txt"; // 获取源文件和目标文件的输入输出流 FileInputStream fin = new FileInputStream(infile); FileOutputStream fout = new FileOutputStream(outfile); // 获取输入输出通道 FileChannel fcin = fin.getChannel(); FileChannel fcout = fout.getChannel(); // 创建缓冲区 ByteBuffer buffer = ByteBuffer.allocate(1024); while (true) { // clear方法重设缓冲区,使它可以接受读入的数据 buffer.clear(); // 从输入通道中将数据读到缓冲区 int r = fcin.read(buffer); // read方法返回读取的字节数,可能为零,如果该通道已到达流的末尾,则返回-1 if (r == -1) { break; } // flip方法让缓冲区可以将新读入的数据写入另一个通道 buffer.flip(); // 从输出通道中将数据写入缓冲区 fcout.write(buffer); } }}
参考文章:NIO入门
- NIO浅析
- NIO浅析
- 浅析NIO
- 【IO/NIO】Java NIO浅析
- 浅析tomcat nio 配置
- 浅析Tomcat NIO 配置
- 浅析tomcat nio 配置
- 浅析Tomcat NIO 配置
- 浅析Tomcat NIO 配置
- 浅析tomcat nio 配置
- Java NIO浅析
- Java NIO浅析
- Java NIO浅析
- Java NIO浅析
- Java NIO浅析
- Java NIO浅析
- 【总结】Java NIO浅析
- NIO selector原理浅析
- [C] 跨平台使用TCHAR——让Linux等平台也支持tchar.h,解决跨平台时的格式控制字符问题,多国语言的同时显示(兼容vc/gcc/bcb,支持Windows/Linux/Mac)
- TP的display与系统变量
- hudson集成
- Android 如何计算CPU使用率(CPU Usage)
- 树和森林的周游
- NIO浅析
- 冯诺依曼体系结构与哈弗体系结构的区别
- Programming ASP.NET MVC-Fundamentals of ASP.NET MVC(四)Routing
- CF:Ilya and Bank Account
- 字符统计算法
- 文档复制及顺序加编号
- TP中的ajax请求
- 冯·诺依曼结构
- hudson任务配置说明