您的位置:首页 > 编程语言 > Java开发

NIO学习系列笔记(1)

2015-11-12 17:40 302 查看
在JDK1.4以前,I/O输入输出处理,我们把它称为旧I/O处理,在JDK1.4开始,java提供了一系列改进的输入/输出新特性,这些功能被称为新I/O(NEW I/O),新添了许多用于处理输入/输出的类,这些类都被放在java.nio包及子包下,并且对原java.io包中的很多类以NIO为基础进行了改写,新添了满足新I/O的功能。

  旧I/O中,java.io包中的类,如BufferedReader读取输入流中的数据时,如果没有读到有效数据时,程序将在此处阻塞该线程的执行(InputStream中的read方法也是如此),简单一点说,旧的i/o流,是属于阻塞式输入,输出.而且传统的输入,输出都是通过字节的移动来处理,也就是说面向流的输入/输出系统一次只能处理一个字节,因此面向流的输入/输出系统通常效率不高.所以就出现了新I/O了。

  新IO和传统的IO有相同的目的,都是用于进行输入/输出功能,但新IO使用了不同的方式来处理输入输出,新IO采用内存映射文件的方式来处理输入输出,新IO将文件或文件的一段区域映射到内存中,这样就可以象访问内存一样来访问文件了,通过这种方式来进行输入输出比传统的输入输出要快得多.
JAVA中NIO相关的包如下

java.nio 包
:主要提供了一些和Buffer相关的类
java.nio.channels包:主要包括Channel和Selector相关的类
java.nio.charset包:主要包含和字符集相关的类
java.nio.channels.spi包:主要包含提供Channel服务的类
java.nio.charset.spi包:主要包含提供字符集服务的相关的类

Channel(通道)和Buffer(缓冲)是新io中的两个核心对象

  Channel是对传统输入输出系统中的模拟,在新io系统中所有数据都需要通过通道传输;Channel与传统瓣InputStream、OutputStream最大的区别在于它提供了一个map方法,通过该map方法可以直接将“一块数据”映射到内存中。如果说传统的输入输出系统是面向流的处理,而新io则是面向块的处理.

  Buffer可以理解成一个容器,它的本质是一个数组,发送到Channel中的所有对象都必须首先放到Buffer中,而从Channel中读取的数据也必须先读到Buffer中.此处的Buffer有点类似于“竹筒”,该Buffer既可以象前面那样一次,一次去Channel中取水,也允许使用Channel直接将文件的某块数据映射成Buffer
(一)使用Buffer

   从内部结构上来看,Buffer就象一个数组,它可以保存多个类型相现的数据。Buffer是一个抽象类,其最常用的子类是ByteBuffer,它可以在底层字节数组上进行 get/put操作,除了 ByteBuffer之外,对应其它数据类型(boolean除外),都有相应的Buffer类:ByteBuffer,CharBuffer,ShortBuffer,IntBuffer,LongBuffer,FloatBuffer,DoubleBuffer.

   上面这些Buffer类,除了ByteBuffer之外,它们都采用相同或相似的方法来管理数据,只是管理的数据类型不同而也。这些Buffer都没有提供构造器,通过使用如下方法来得到一个Buffer对象.
static XxxBuffer allocate(int capacity):创建一个容量为capacity的XxxBuffer对象

   实际使用较多的是ByteBuffer和CharBuffer,其它Buffer子类则较少用到.

在Buffer有三个重要的概念:容量(Capacity),界限(limit),和位置(position)

容量(Capacity):
缓冲区的容量表示 该Buffer的最大数据容量,即最多可以存储多少数据。
界限(limit):第一个不应该被读出或者写入的缓冲区位置索引.也就是说,位于limit后的数据既不可读,也不可写
位置(position):用于指明下一个可以被读出的或者写入的缓冲区位置索引(类似于io流的记录指针)

下图是某个Buffer读入了一些数据后的示意图







Buffer有两个非常重要的方法:flip和Clear方法

(1)当Buffer装入数据结束后,调用Buffer的flip方法,该方法将limit设置为position所在位置,将position设为0,这样使得从Buffer中读数据时总是从0开始,读完刚刚装入的所有数据即结束,也说是Buffer调用flip方法后,Buffer为输出数据做好了准备.

(2)当Buffer调用clear方法,clear方法不是清空Bufferr的数据,它仅仅将postion 的位置置为0,将limit置为 capacity,这样为再次向Buffer中装入数据做好了准备.

(3)flip为从Buffer中取出数据做好准备,clear则向Buffer中装入数据做好准备.

下面程序示范了Buffer的一些常规操作
(下面有运行结果,如有疑问,可以留言)

import java.nio.*;

public class BufferTest

{

 public static void main(String[] args)

 {

  //创建Buffer

  CharBuffer buff = CharBuffer.allocate(8); //1

  System.out.println("capacity: "

   + buff.capacity());

    System.out.println("limit: "

   + buff.limit());

    System.out.println("position: "

   + buff.position());

  //放入元素

    buff.put('a'); //2

    buff.put('b'); //3

    buff.put('c'); //4

    

    System.out.println("加入三个元素后,position = "

   + buff.position());

    //调用flip()方法

    buff.flip(); //5

    System.out.println("执行flip()后,limit = "

   + buff.limit());

    System.out.println("position = "

   + buff.position());

    //取出第一个元素

    System.out.println("第一个元素(position=0):"

   + buff.get()); //6    

    System.out.println("取出一个元素后,position = "

   + buff.position());

    //调用clear方法

    buff.clear(); //7

    System.out.println("执行clear()后,limit = "

   + buff.limit()); 

    System.out.println("执行clear()后,position = "

   + buff.position());

    System.out.println("执行clear()后,缓冲区内容并没有被清除:"

   + buff.get(2)); //8

  System.out.println("执行绝对读取后,position = "

   + buff.position());

 }

}

 

运行结果



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  nio java io