1. NIO、NIO.2简介
2. NIO中的关键技术
1. NIO、NIO.2简介
Java中的输入流、输出流都是阻塞式的输入、输出。不仅如此,传统的输入流、输出流都是通过字节的移动来处理的(即使是字符流,在底层也是通过字节流来进行处理的),也就是说,面向流的输入/输出系统一次只能处理一个字节,因此面向流的输入/输出系统通常效率不高。
从JDK1.4开始,java提供了一系列改进的输入/输出处理的新功能,这些功能被统称为新IO(New IO,简称NIO),新增了许多用于处理输入/输出的类,这些类都被放在java.nio包以及子包下,并且对原java.io包中的许多类都以NIO为基础进行了改写。
NIO和传统的IO有相同的目的,都是用于进行输入/输出,但新IO采用内存映射文件的方式来处理输入/输出,新IO将文件或文件的一段区域映射到内存中,这样就可以像访问内存一样来访问文件了
(模拟了操作系统上的虚拟内存的概念),通过这种方式来进行输入/输出比传统的输入/输出要快得多
http://baike.baidu.com/view/394293.htm
java.nio的包层次结构如下
复制代码
1. Buffer
java.nio.Buffer: Buffer是一个对象,它包含一些要写入或者刚读出的数据。在NIO中加入Buffer对象,体现了NIO库与传统I/O的一个重要区别。在面向流的I/O中,我们将数据直接写入或者
将数据直接读到Stream对象中。而在NIO库中,所有数据都是用缓冲区处理的。发送到Channel中的所有对象都必须首先放到Buffer中,而从Channel中读取的数据也必须先放到Buffer中。任何
时候访问NIO中的数据,我们都是将它放到缓冲区中。缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存。这块内存被包装成NIO Buffer对象,并提供了一组方法,用来方便的访问
该块内存。
这些Buffer类都没有提供构造器,而是通过具体子类: XxxBuffer.allocate(int capaticy); 来创建一个容量为capacity的XxxBuffer对象
1.1) ByteBuffer: 字节数组
1.1.1) MappedByteBuffer: 用于表示Channel将磁盘文件的部分或者全部内容映射到内存后得到的结果
1.2) ByteOrder: 字节枚举数组
1.3) CharBuffer: 字符数组
1.4) DoubleBuffer: Double数组
1.5) FloatBuffer: Float数组
1.6) IntBuffer: Int数组
1.7) LongBuffer: Long数组
1.8) ShortBuffer: Short数组
2. Channel
Channel类似于传统的流对象,但与传统的流对象有两个主要区别: 1) Channel可以直接将指定文件的部分或者全部直接映射成Buffer。2) 程序不能像访问流那样直接访问Channel中的数据
(包括读取、写入),Channel只能和Buffer进行交互。即,如果要从Channel中取得数据,必须先使用Buffer从Channel中取出一些数据,然后让程序再从Buffer中取得这些数据。写入也一样。
和Buffer一样,所有的Channel都不应该通过构造器来直接创建吗,而是通过传统的节点InputStream、OutputStream的getChannel()方法来返回对应的Channel,不同的节点流获得的
Channel是不一样的。从这个角度理解,Channel也可以理解为对节点流的一种包装流,这也是Java中著名的装饰器设计模式的一种体现。
我们按照Channel的功能对Channel的类层次进行分类
1) 文件操作
1.1) FileChannel:
文件读写的通道
1.1.1) FileInputStream调用getChannel返回的是只能读的FileChannel
1.1.2) FileOutputStream调用getChannel返回的是只能写的FileChannel
1.2) AsynchronousFileChannel: NIO.2新增了异步文件操作方式
1.3) FileLock: 文件锁、互斥读写
2) 非阻塞式输入输出
2.1) SelectableChannel
2.2) Selector
2.3) SelectionKey
3) java.nio.channels.Pipe: 线程通信
3.1) Pipe.SinkChannel: PipedInputStream调用getChanel()返回的是Pipe.SinkChannel
3.2) Pipe.SourceChannel: PipedOutputStream调用getChanel()返回的是Pipe.SourceChannel
4) NetworkChannel: 支持TCP网络通信的Channel
4.1) ServerSocketChannel
4.2) AsynchronousServerSocketChannel
4.3) SocketChannel
4.4) AsynchronousSocketChannel
5) DatagramChannel: 支持UDP网络通信的Channel
3. Charset
计算机底层是没有文本文件的、图片之分的,它只是记录每个文件的二进制数据。当需要保存文本文件时,程序必须先把文件中的每个"字符"翻译成二进制序列,当需要读取文本文件时,
程序必须把二进制序列转换成一个个的"字符"。java默认使用Unicode字符集,为了解决可能出现的乱码等问题。JDK 1.4提供了Charset来处理字节序列和字符序列(字符串)之间的转换关系
(单字节、双字节),该类包含了用于创建解码器、编码器的方法。
1) Charset
一旦知道了字符集的别名之后,程序就可以调用Charset的forName()方法来创建对应的Charset对象,forName()方法的参数就是相应字符集的别名
2) CharsetEncoder
获得了Charset对象之后,就可以通过该对象的newEncoder()方法来返回对应的编码器,调用CharsetEncoder的encode()方法可以完成字符序列(CharBuffer、String)到字节序列
(ByteBuffer)的转换
3) CharsetDecoder
获得了Charset对象之后,就可以通过该对象的newDecoder()方法来返回对应的解码器,调用CharsetDecoder的decode