Java I/O之NIO概念理解
JDK1.4的java.nio.*包引入了新的Java I/O新类库,其目的在于提高速度。实际上,旧的I/O包已经使用nio重新实现过,以便充分利用这种速度提高,因此即使我们不显式地用nio编码,也能从中受益。
通道(Channel)和缓冲器(ByteBuffer)
NIO速度的提高其实来自于所使用的结构更接近于操作系统执行I/O方式:通道和缓冲器。通道和缓冲器的关系你可以这样在脑海里建立一个概念模型:想象一个煤矿,通道就是链接矿藏和外界的矿井,而缓冲器是在矿井运输煤炭的卡车。卡车满载后通过矿井远处到外界,我们就可以从卡车上获取到煤炭。而我们没有直接和通道交互,而只是和缓冲器交互,而通道要么从缓冲器获取数据,要么向缓冲器发送数据。如下图:

NIO修改了旧IO的三个类用于产生FileChannel:FileInputStream、FileOutputStream和RandomAccessFile。这些都是字节流而不是字符流。我们先通过代码来形象地了解下用法吧。
//缓冲器
ByteBuffer buf=ByteBuffer.allocate(1024);
//输出通道
FileChannel out=new FileOutputStream("d:"+File.separator+"data.txt").getChannel();
//数据写入缓冲器
buf.asCharBuffer().put("this is a demo txt.");
//通道操作缓冲器
out.write(buf); //输入通道
FileChannel in=new FileInputStream("d:"+File.separator+"data.txt").getChannel();
//清空缓冲器
buf.clear();
//通道操作缓冲器
in.read(buf);
//设置缓冲器可读位置
buf.flip();
System.out.println(buf.asCharBuffer());
输出
this is a demo txt.
通道Channel
通道是缓冲器连接数据源或数据目的地的连接,直接操纵缓冲器读写数据。
java.nio.channels包中定义了通道API,包括FileChannel、Socket通道SocketChannel、ServerSocket通道ServerSocketChannel、数据报通道DatagramChannel。本篇暂不介绍Socket通道。
Java的通道关系图如下:

Channel接口的两个最重要的子接口是ReadableByteChannel和WritableByteChannel。
- ReadableByteChannel定义了一个可从中读取byte数据的Channel接口,该接口定义了read(ByteBuffer dst)方法,该方法把数据源的数据读入指定的ByteBuffer缓冲区中。
- WritableByteChannel接口声明了write(ByteBuffer dst)方法,该方法把参数指定的ByteBuffer缓冲区中的数据写到数据汇中。
这里我们不做深入探讨,有兴趣的同学可以直接查看Java源码。
缓冲器ByteBuffer
从Java的类库来看,ByteBuffer只是众多Buffer的其中一员:

这里我也不做深入分析,我们只来简单了解下ByteBuffer从Buffer继承的几个方法clear()、flip()和rewind(),以及ByteBuffer的视图。
ByteBuffer说白点就是对一个定长数组的包装。里面有几个指针控制读写的位置和范围。数组的长度是capacity,读写的当前位置是position,读写范围的结束地点为limit。position的位置会随着读写向后移动,当到达limit位置时会报出响应的异常。比如读的范围超过了limit,会报BufferUnderflowException,如果写的时候超过了limit,会报BufferOverflowException。position和limit都提供了相应方法设置和获取,使用起来相当灵活。下面的图演示了ByteBuffer的主要结构:

一般情况下,我们往ByteBuffer写入数据时,会先调用clear方法,将position设置成0,limit设置成capacity,然后开始调用ByteBuffer的各种put方法来塞入数据;当我们从ByteBuffer中读数据时,会先调用ByteBuffer的flip方法将position重置为0、limit设置为当前的position,读取ByteBuffer中的数据。
常用的缓冲器方法:
static ByteBuffer allocate(int capacity) //分配一个新的字节缓冲区。
final Buffer clear()//清除此缓冲区。将位置设置为 0,将限制设置为容量,并丢弃标记。
final Buffer flip()//首先将限制设置为当前位置,然后将位置设置为 0。如果已定义了标记,则丢弃该标记。
final Buffer rewind()//将位置设置为 0 并丢弃标记。
final Buffer mark()//在此缓冲区的当前位置设置标记。
final Buffer reset()//将此缓冲区的位置重置为以前标记的位置。
缓冲器有多个视图,如
CharBuffer asCharBuffer()
创建此字节缓冲区的视图,作为 char 缓冲区,新缓冲区的内容将从此缓冲区的当前位置开始。此缓冲区内容的更改在新缓冲区中是可见的,反之亦然;这两个缓冲区的位置、界限和标记值是相互独立的。
还有很多视图如:asDoubleBuffer() 、asFloatBuffer() 、asIntBuffer()等等,以及众多方法,再次不意义累述,请查阅JDK API文档。
本篇博文就此结束,估计没过瘾吧?!其实这里主要是通道和缓冲器的理解,理解后再对照JDK API文档练习即可,熟能生巧。
Java I/O之NIO概念理解的更多相关文章
- Java基础中的一些概念理解
同步 和 异步区别 同步和异步通常用来形容一次方法的调用. 同步方法调用一旦开始,调用者必须等到方法调用返回后,才能继续后续的行为.而异步方法调用更像一个消息传递,一旦开始,方法调用就会立即返回,调用 ...
- Java网络编程和NIO详解开篇:Java网络编程基础
Java网络编程和NIO详解开篇:Java网络编程基础 计算机网络编程基础 转自:https://mp.weixin.qq.com/s/XXMz5uAFSsPdg38bth2jAA 我们是幸运的,因为 ...
- Java网络编程和NIO详解9:基于NIO的网络编程框架Netty
Java网络编程和NIO详解9:基于NIO的网络编程框架Netty 转自https://sylvanassun.github.io/2017/11/30/2017-11-30-netty_introd ...
- Java网络编程和NIO详解5:Java 非阻塞 IO 和异步 IO
Java网络编程和NIO详解5:Java 非阻塞 IO 和异步 IO Java 非阻塞 IO 和异步 IO 转自https://www.javadoop.com/post/nio-and-aio 本系 ...
- Java网络编程和NIO详解2:JAVA NIO一步步构建IO多路复用的请求模型
Java网络编程与NIO详解2:JAVA NIO一步步构建IO多路复用的请求模型 知识点 nio 下 I/O 阻塞与非阻塞实现 SocketChannel 介绍 I/O 多路复用的原理 事件选择器与 ...
- Java的BIO,NIO,AIO
Java中的IO操作可谓常见.在Java的IO体系中,常有些名词容易让人困惑不解.为此,先通俗地介绍下这些名词. 1 什么是同步? 2 什么是异步? 3 什么是阻塞? 4 什么是非阻塞? 5 什么是同 ...
- Java反射机制的基本概念与使用
本篇文章分为以下几个部分: 1.认识反射 2.反射的源头(Class类) 3.利用反射操作构造方法 4.利用反射调用类中的方法 5.反射中的invoke方法 6.利用反射调用类中的属性 反射在我们普通 ...
- Java的BIO和NIO很难懂?用代码实践给你看,再不懂我转行!
本文原题“从实践角度重新理解BIO和NIO”,原文由Object分享,为了更好的内容表现力,收录时有改动. 1.引言 这段时间自己在看一些Java中BIO和NIO之类的东西,也看了很多博客,发现各种关 ...
- Java工程师学习指南第5部分:Java网络编程与NIO
本文整理了微信公众号[Java技术江湖]发表和转载过的Java网络编程相关优质文章,想看到更多Java技术文章,就赶紧关注本公众号吧. 深度解读 Tomcat 中的 NIO 模型 [Java基本功]浅 ...
随机推荐
- js判断ip地址,子网掩码,网关的逻辑性检查
因为要做静态地址配置的js校验,找了好多资料发现网上都是关于ip,mask的有效性检查,没有ip,submask,gateway的逻辑性判断,自己写下代码供需要的人参考. 普及下网关地址知识: 就是进 ...
- cygwin下配置alias
主要是cygwin下的盘符映射关系容易忘,直接用mount命令: 所以,找到E:\cygwin64\home\Administrator下面的.bashrc,添加alias.如下:
- HDU-1862-EXCEL排序
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1862 这个题考的就是你对sort函数的掌握:会用sort函数对字符串,数字排序,只要懂得话题目很简单 ...
- 笔记:Ubuntu 上的Testlink 部署
1.安装apache2 sudo apt-get install apache2 2. sudo /etc/init.d/apache2 restart 测试: Http:\localhost or ...
- 【G】开源的分布式部署解决方案 - 预告篇
为什么想到要做分布式部署解决方案? 当项目越做越大以后,你会发现部署变成一件极其头疼的事情.当然头疼的绝不仅仅在部署一个环节,比如新服务器环境搭建当中就许多坑要踩.各种重复性的工作,包括但不仅限于增加 ...
- Java日期工具类,Java时间工具类,Java时间格式化
Java日期工具类,Java时间工具类,Java时间格式化 >>>>>>>>>>>>>>>>>&g ...
- <C++Primer>第四版 阅读笔记 第二部分 “容器和算法”
泛型算法中,所谓"泛型(generic)"指的是两个方面:这些算法可作用于各种不同的容器类型,而这些容器又可以容纳多种不同类型的元素. 第九章 顺序容器 顺序容器的元素排列次序与元 ...
- CSS中:visited的隐私保护
CSS 伪类 (Pseudo-classes) 锚伪类:在支持 CSS 的浏览器中,链接的不同状态都可以不同的方式显示,这些状态包括:活动状态,已被访问状态,未被访问状态,和鼠标悬停状态. a:lin ...
- (@WhiteTaken)Unity中Invoke的用法
今天无意间读到大神写的代码,看到了Invoke函数,于是产生兴趣.后来才明白自己要学习的东西还有很多. 下面讲用法. Invoke是延时调用函数,在用Invoke函数之前需要引入命名空间using U ...
- asp.net core mvc剖析:启动流程
asp.net core mvc是微软开源的跨平台的mvc框架,首先它跟原有的MVC相比,最大的不同就是跨平台,然后又增加了一些非常实用的新功能,比如taghelper,viewcomponent,D ...