一.NIO 和BIO的比较
NIO是jdk1.4开始提供的一种新的IO方式。原来的 I/O 库(在 java.io.*中) 与 NIO 最重要的区别是数据打包和传输的方式。原来的 I/O 以流的方式处理数据,而 NIO 以块的方式处理数据。面向流 的 I/O 系统一次一个字节地处理数据。一个输入流产生一个字节的数据,一个输出流消费一个字节的数据。为流式数据创建过滤器非常容易。链接几个过滤器,以便每个过滤器只负责单个复杂处理机制的一部分,这样也是相对简单的。不利的一面是,面向流的 I/O 通常相当慢。
一个 面向块 的 I/O 系统以块的形式处理数据。每一个操作都在一步中产生或者消费一个数据块。按块处理数据比按(流式的)字节处理数据要快得多。但是面向块的 I/O 缺少一些面向流的 I/O 所具有的优雅性和简单性。这里需要说明为什么面向块的IO要比面向流的IO要快,举例来说应用程序从磁盘读取数据的时候其实并不是直接从磁盘取数据的而是先由操作系统把磁盘上的数据读到系统内存中,这一步是操作系统的IO,不由应用程序控制;然后应用程序再把数据从系统内存读取到应用内存中去,后一步也就是我们程序中的IO操作。操作系统一般一次将一块的数据由磁盘移动到系统内存上去,基于块的IO和基于流IO的不同之处在于基于流的IO需要一个个字符的把系统内存上的数据移动到应用内存上去,而基于块的IO会一次一块的将数据移动到应用内存,效率自然是基于块的IO更好。但在jDK1.4之后,BIO的底层也使用NIO方式进行了部分重写,所以就文件读写效率方面来说,两者差别已经不大,最重要的差别还是NIO提供了异步非阻塞的网络编程模型,这是BIO所不能实现的。
二.NIO的核心概念—通道和缓冲区
通道对应NIO中的Channel类,通道类似于基础IO中的流(InputStream/OutputStream),数据的读取和写入都需要经过通道; 缓冲区对应NIO中的Buffer类,可以认为它是一个容器,所有需要写入到通道中去或需要从通道中读取的数据都需要放置在buffer中。
1)Channel
Channel和流很多方面都是类似的,最大的不同在于流是单向的而Channel是双向的。可以按不同的数据源类型将Channel进行分类FileChannel,DatagramChannel,SocketChannel,
ServerSocketChannel,分别对应了文件IO和网络IO。另外,Channel对象一般都是通过对应类的静态工厂方法或对应流的getChannel()方法得到的,不能通过new关键字创建一个Channel对象。下面演示通过Channel来将一个文件中的内容复制到另外一个文件中去,可以看到操作其实和BIO的读取写入很类似,不同的地方是数据的读取和写入都使用了到了ByteBuffer对象,而不是常用的byte[]。
long ctime = System.currentTimeMillis();
FileInputStream fileInputStream = new FileInputStream("/test/poiList.txt");
FileOutputStream fileOutputStream = new FileOutputStream("/test/poiList2.txt");
FileChannel in = fileInputStream.getChannel();
FileChannel out = fileOutputStream.getChannel()