1. 基本 概念
IO 是主存和外部设备 ( 硬盘、终端和网络等 ) 拷贝数据的过程。 IO 是操作系统的底层功能实现,底层通过 I/O 指令进行完成。
所有语言运行时系统提供执行 I/O 较高级别的工具。 (c 的 printf scanf,java 的面向对象封装 )
2. Java 标准 io 回顾
Java 标准 IO 类库是 io 面向对象的一种抽象。基于本地方法的底层实现,我们无须关注底层实现。 InputStream\OutputStream( 字节流 ) :一次传送一个字节。 Reader\Writer( 字符流 ) :一次一个字符。
3. nio 简介
nio
是
java New IO
的简称,在
jdk1.4
里提供的新
api
。
Sun
官方标榜的特性如下:
– 为所有的原始类型提供 (Buffer) 缓存支持。
– 字符集编码解码解决方案。
– Channel :一个新的原始 I/O 抽象。
– 支持锁和内存映射文件的文件访问接口。
– 提供多路 (non-bloking) 非阻塞式的高伸缩性网络 I/O 。
本文将围绕这几个特性进行学习和介绍。
4. Buffer&Chanel
Channel
和
buffer
是
NIO
是两个最基本的数据类型抽象。
Buffer:
– 是一块连续的内存块。
– 是 NIO 数据读或写的中转地。
Channel:
– 数据的源头或者数据的目的地
– 用于向 buffer 提供数据或者读取 buffer 数据 ,buffer 对象的唯一接口。
– 异步 I/O 支持
java原来的I/O体系中, I/O实际上是以Stream(流)这个抽象概念被使用,所有的I/O实际上被看做是单个字节一个字节一个字节的移动; Stream I/O被用来和外界世界交互,在内部它用来将对象转为bytes字节流,然后再转为对象;
NIO的角色和目标实际上和原来的I/O是相同的,但是它使用了一个不同的抽象概念:block I/O. 正如你将所见到的那样,block I/O比原来的I/O有效率得多;
Streams和blocks的对比
原来的I/O包和NIO处理数据最大的不同之处在于数据打包(packaged)和传输(transmitted)的方式。正如前面所提到的那样,IO(java.io.*)是以流的方式处理数据的,而NIO是以blocks(块)的方式来处理数据的.
一个流面向(stream-oriented)的I/O系统在处理数据时是一次只处理一个字节;作为input的stream一次向计算机生产一个byte,作为output的stream一次向计算机要求消费一个byte(计算机生产byte),对stream创建filter是一件非常容易的事情,同时如果你希望通过chain模式将几个filter连在一起也很容易,最终可以将大量复杂的处理分成一个简单,巧妙的处理模式;但是同时,stream-oriented的I/O处理通常非常低效率。
而一个块面向(block-oriented)的I/O系统成块的处理数据,每次操作都会生产或者消费以block为单位的数据;所以,这种方式会比stream-oriented的处理方式高效地多,但是block-oriented的I/O也缺少以stream-oriented编程时的简单和优雅;
什么是buffer?:
当数据写入或者数据读取时,这些数据被保存在一个buffer对象中;buffer对象是nio和原io包中一个最重要的区别。在原来的io系统中,数据的读取和获得是首先通过Stream流对象。
在nio中,所有的数据采用buffers的方式进行处理。当数据被读取的时候,读入数据被先保存到buffer中;数据写入的时候,写入数据也首先放置到buffer中。
一个buffer对象实际上是一个array对象,但是又不单单只具有array的功能;一个buffer对象提供了结构化访问数据的能力,并且记录了系统读/写操作的日志。
buffer的类型?:
最常见的使用buffer的方式是ByteBuffer,一个ByteBuffer的底层数组允许get/set buffers的操作;
其他的buffer类型包括:CharBuffer,ShotBuffer,
IntBuffer, LongBuffer, DoubleBuffer,FloatBuffer;
每一种buffer的类型都是一个buffer接口;这些接口的行为除了处理的数据不同之外, 操作行为非常相似; 不过因为ByteBuffer被用来和大多数标准的I/O操作,所以除了共有的buffer操作之外,还有一些特别的操作行为;
什么是channel?:
一个Channel是一个可以操作读写数据的对象,channel的概念类似于io包中的stream(流)概念;
如前所述,在nio中,所有的数据是通过buffer这个对象进行处理的;在读写数据的时候,你永远不需要直接地操作Channel对象;
channel的类型?:
和io中流(Stream)概念不同的是,channel是双向的;一个流必须是InputStream或者OutputStream的子类,一个Channel可以是读/写操作的任何一种或两种;因为channel的双向特性,和流比起来更真实地反映了os的底层,尤其在Unix中。