Java NIO的出现旨在提高文件的读写速度,当然IO用NIO重新实过,所以我们不用显示的调用NIO也能享受这种高效的文件读写。

  Java NIO的高效得益于其两大"助手":Channel(管道)和Buffer(缓冲器)。当然这两个"得力助手"的"年龄"远远比java大!力求简单易懂的把知识讲解给大家,我举一个例子来说明一下这"两元大将"是如何在java NIO中配合工作的。

  中国古代有一种传统的吸烟器具---水烟袋。我想用这个东西来模拟一下Channel和Buffer的工作原理。不求说的好,力求准确无误。

分析一下水烟袋是如何工作的:

  第一步,准备工作,准备好上等烟丝;第二步,将"水斗"中装入适量的水,烟仓中装满烟丝并插入水斗中,然后再将烟管插入水斗中;第三步,点燃烟丝并吸气。香烟从烟仓产生,经过水的过滤进入水上的空闲区。第四步,享受吸烟的快感.....从这个例子中我们提取出主要对象"烟",来分析一下它的运动轨迹。烟仓把烟生产出来,经过水的过滤飘到水上面的空闲区域,然后通过烟管进入人的体内。

  如果上面的过程大家理解了,明白了,那么java NIO你已经了解了50%,至少你已经知道它的工作原理了。因为用NIO处理的数据和用水烟袋中吸烟很相似。我们分析一下NIO的工作原理,非常简单。

  当然和吸烟一样我们首先必须有要用NIO来处理需求的欲望(这好比你想要吸烟了),比方说我想要将C盘下面的wk.txt文件进行备份,备份文件的名称为wk-bak.txt。类比刚刚吸烟的那个过程:

  步骤一:准备工作,确定文件的位置,并将程序不可直接操作的文件转换成字符流的形式(这一步和上边吸烟实例的第一步没有什么差别,只是进行一些简单的准备工作)。

String inFile = "C:\\wk.txt";String outFile = "C:\\wk-bak.txt";FileInputStream inf = new FileInputStream(inFile);FileOutputStream outf = new FileOutputStream(outFile);ByteBuffer buffer = ByteBuffer.allocate(1024);

  步骤二:创建文件输入管道,和文件输出管道。(这一步与上边吸烟的第二部稍有差别,因为Channel和Buffer是在读写的时候才发生的"连接"动作)

//准备文件读取的管道-->相当于烟仓和烟管FileChannel inFc = inf.getChannel();FileChannel outFc = outf.getChannel();

Charset charSet = Charset.forName("utf-8");//进行编码解码-->相当于水斗中水的过滤作用CharsetDecoder decoder = charSet.newDecoder();CharsetEncoder encoder = charSet.newEncoder();  

  步骤三:开始进行文件备份工作。

       while(true) {            //准备向Buffer中写入数据-->相当于点燃烟丝,完事具备只欠东风            buffer.clear();

            //进行字符编码 -->相当于水的过滤作用            CharBuffer cb = decoder.decode(buffer);            ByteBuffer bb = encoder.encode(cb);

            //数据经过编码以后暂存缓冲区-->相当于经过水过滤后的烟暂停在水斗中            int t = inFc.read(bb);            if(t == -1) {                break;            }

            bb.flip();

            //将字节码写入目标文件-->相当于烟已经进入到嘴里            outFc.write(bb);        }

  步骤四:检查文件是否备份成功。发现C盘下面多了一个wk-bak.txt的文件,内容与wk.txt一摸一样。接下来享受java带给你的快感....

  上面的例子估计大家已经理解的差不多了,当然如果深究也会有一些不太妥当的地方,但是不要较真,目的是学习NIO,并不是吸烟。如果感觉你可以了那么就请把上面的例子补充完整,运行一下,享受一下NIO的威武(当然字符编码并不是必须的,只是让这个例子显得完整一点)。

  好吧如果你理解了上面的东西,并且真正的补全了文件备份的小程序,那么就来进行稍微深入一点的学习吧。

  上文我提到了举吸烟的例子是有欠妥当的,其中之一就是Buffer的内部机制和"水斗"简单的过滤功能是不一样的。还有字符编码那一块也不是在Buffer内部实现的东西,decoder和encoder是针对Buffer的两个工具。那我们接下来分析一下Buffer内部机制到底不一样在哪里呢(主要分析常用的两个方法;clear(),flip())?

  来吧,打开Buffer的源码(摘取有用的部分):

public abstract class Buffer {

    // Invariants: mark <= position <= limit <= capacity    private int mark = -1;    private int position = 0;    private int limit;    private int capacity;

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

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

 首先我们要明确一点,所谓的缓冲器仅仅是一个"多功能"的数组。可能在这个Buffer类中没有体现,但是如果我们打开ByteBuffer的源码会有byte[]的数组,打开CharBuffer的源码会有char[]的数组。因为Buffer是所有缓冲器的父类,所以他它不能预计会有多少种缓冲器,所以索性让"儿子"们自己实现去吧。

  既然知道了缓冲器是一个"多功能的数组",那么我们用画图的形式来分析一下上面Buffer的源码。

假设我们定义了一个8个单位大的缓冲区,如上图(其实Buffer也就是这么一个东西)。首先告诉大家那三个重要的关于缓冲区状态的的属性:

  capacity:缓冲区的容量;

  limit:缓冲区还有多少数据能够取出或者缓冲区还有多少容量用于存放数据;

  position:相当于一个游标(cursor),记录我们从哪里开始写数据,从哪里开始读数据。

刚还说到flip()和clear()是Buffer的两个重要的方法,因为它们两个方法决定了缓冲是否能正常的进行读写工作。

  当我们要想从缓冲区中写数据的时候必须先执行flip()方法,当我们要想从缓冲区中读数据时必须先执行clear()方法。

第一次向Buffer中写入数据时,执行一次flip()方法以后,Buffer的结构变成了这样:position指向了第一个可以存取数据的0号位,limit和capacity同时指向最高位。

假如第一次我们向Buffer中写入了3单位的数据,我们再次执行flip()方法则Buffer的结构会变成上图的所示。但是经过flip()的改造后position总是指向Buffer中第一个可用的位置。那么,未执行flip()方法以前position在哪里呢?很简单,指向最后一个数据的位置。

当我们想要从Buffer中读取数据时,执行clear()方法,Buffer的内部结构变成了上图所示,position指向了可读数据的首位,limit指向了原来position的位置。

  从上面的几幅图中我们看出:capacity代表了Buffer的容量是不变的,limit与position的差总是表示Buffer总可以读的数据,或者Buffer中可以写数据的容量。还有position总是小于等于limit,limit总是小于等于capacity。

  其实到这里我们已经发现,NIO并不像IO那么复杂,因为IO 中的Decorator模式和Adaptor模式确实让我们一时间摸不到头脑,但是熟悉了会感觉到IO的设计之精美。

  NIO中还有一个知识点就是无阻塞的Socket编程,这里就不说了,因为比较复杂,但是如果我们真正理解了Selector这个调度者的工作,那么无阻塞的实现机制我们差不多就掌握了,复杂也就是编码上面的事了。

转载于:https://www.cnblogs.com/firstdream/p/5536022.html

我来说说java的NIO相关推荐

  1. 理解Java的NIO

    同步与阻塞 同步和异步是针对应用程序和内核的交互而言的. 同步:执行一个操作之后,进程触发IO操作并等待(阻塞)或者轮询的去查看IO的操作(非阻塞)是否完成,等待结果,然后才继续执行后续的操作. 异步 ...

  2. 【Java】NIO中Selector的select方法源码分析

    该篇博客的有些内容和在之前介绍过了,在这里再次涉及到的就不详细说了,如果有不理解请看[Java]NIO中Channel的注册源码分析, [Java]NIO中Selector的创建源码分析 Select ...

  3. java之NIO(Channel,Buffer,Selector)

    java之NIO 1 什么是NIO Java NIO (New IO,Non-Blocking IO)是从Java 1.4版本开始引入的一套新的IO API.NIO支持面向缓冲区的.基于通道的IO操作 ...

  4. JAVA之NIO按行读写大文件,完美解决中文乱码问题

    JAVA之NIO按行读写大文件,完美解决中文乱码问题 参考文章: (1)JAVA之NIO按行读写大文件,完美解决中文乱码问题 (2)https://www.cnblogs.com/jpfss/p/89 ...

  5. 【IO专栏】Java OIO NIO通信对比分析【002】

    在1.4版本之前,Java IO类库是阻塞IO:从1.4版本开始,引入了新的异步IO库,被称为Java new IO 类库,new IO 类库的目标,就是要让Java支持非阻塞IO,基于这个原因更多人 ...

  6. java aio nio bio_3. 彤哥说netty系列之Java BIO NIO AIO进化史

    你好,我是彤哥,本篇是netty系列的第三篇. 欢迎来我的公从号彤哥读源码系统地学习源码&架构的知识. 简介 上一章我们介绍了IO的五种模型,实际上Java只支持其中的三种,即BIO/NIO/ ...

  7. Java中nio、bio和aio的区别

    前言:IO的方式通常分为几种,同步阻塞的BIO.同步非阻塞的NIO.异步非阻塞的AIO.现在使用NIO的场景越来越多,很多网上的技术框架或多或少用到了NIO技术,譬如Tomcat.Jetty,还有基于 ...

  8. 死磕Java之NIO与IO

    死磕Java之NIO与IO 当学习Java NIO与IO时,你是否会有这样的想法:什么时候使用NIO,什么使用IO呢?本篇文章将会分析两者的不同,它们的用例,以及和影响代码的设计. 01 NIO与IO ...

  9. java 开源 server_simplewebserver: SimpleWebServer 是一款使用Java基于NIO编写的超轻量级开源Web Application Server...

    SimpleWebServer SimpleWebServer 是一款使用Java基于NIO编写的超轻量级开源Web Application Server 是否遇到有时候想做一些小的Web程序,但是迫 ...

  10. 整理自《Pro Java 7 NIO.2》

     http://developer.51cto.com/art/200911/165703.htm http://developer.51cto.com/art/201112/307728.htm ...

最新文章

  1. 变更控制管理流程图_干货丨项目管理流程及绘制规范要点
  2. pandas使用query函数查询指定日期索引对应的dataframe数据行(select rows using a single date in dataframe)
  3. fedora利用vmlinuz和initrd制作linux启动u盘,Fedora 17的U盘安装方法
  4. HTML 5 令人期待的 5 项功能
  5. C# 将List中的数据导入csv文件中
  6. Spring、Spring MVC、Struts2、、优缺点整理
  7. 数学公式、可视化图齐齐上阵,神经网络如何一步步走向最优化「看得见」!...
  8. python记录日志_记录python日志
  9. IO流的应用_Copy文件
  10. Linux命令(20)linux服务器之间复制文件和目录
  11. 博文视点云原生书单丨释放云原生技术红利
  12. JS1 js获取dom元素方法
  13. 全球首次!玩5G日本来了一波骚操作
  14. IE6 position:fixed bug (固定窗口方法)
  15. Redis数据库入门基础知识
  16. 蔡勒公式与Python
  17. java中文转英文_Java中文转换为英文拼音
  18. canvas教程11-渐变
  19. 戴尔服务器的作用是什么,戴尔 PowerEdge M910 管理功能强大
  20. Python 爬抖音

热门文章

  1. outlook本地存储设置_商务文档为什么要存储在OneDrive for business 上?
  2. java robot 文档_文件配置 · simple-robot 机器人开发者使用文档 · 看云
  3. android ztree,ztree实现权限功能(横向显示)
  4. php怎么解析xml,使用PHP快速解析复杂的XML文件
  5. 怎么把文件导入python_如何导入其他Python文件?
  6. android服务自动重启,安卓service关闭后怎么自动重启
  7. 不等号属于不等式吗_初中数学——中考知识3【方程与不等式(基础)】
  8. 工业机器人焊钳制作_一种工业焊接机器人及其冷却装置的制作方法
  9. 我学的技术,过时?被淘汰?
  10. python编程基础_月隐学python第一课