I/O(二)—— NIO

一、NIO概述
  1. IO是阻塞的,NIO是非阻塞式的
  2. IO是面向流的(一次处理一字节,效率不高),NIO是面向块的
  3. IO是单线程的,NIO 是通过选择器来模拟多线程的

NIO在基础的IO流上发展处新的特点,分别是:内存映射技术,字符及编码,非阻塞I/O和文件锁定。
Channel(通道)和Buffer(缓冲)是NIO中的两个核心对象。

  1. Channel类似于传统IO中的流对象,其与InputStream和OutputStream最大的区别在于它提供了一个map()方法,通过该map()实现将一块数据直接映射到内存道中。
  2. Buffer可被理解为一个容器,本质是一个数组,发送到Channel中的对象和从Channel中读取数据时都必须先放到Buffer中。
二、Buffer

I/O(二)—— NIO
这些Buffer类都不提供构造器,而是通过static XxxBuffer allocate(int capacity)来创建一个Buffer对象。Buffer有三个重要的概念:

  1. 容量(capacity):缓冲区容量大小,表示该Buffer最大数据容量。创建后不可改变。
  2. 界限(limit):第一个不该被读出或写入的缓冲区位置索引。
  3. 位置(position):用于指明下一个可被读出或写入的缓冲区位置索引。
    I/O(二)—— NIO当Buffer装入数据结束后,调用flip(),将limit设置为position所在位置,将position设置为0。
    当数据输出结束后,调用clear(),将limit置为position,将position值为0,并不清除Buffer中的原有数据。
    可通过put()、get()方法向Buffer中存、取数据。
三、Channel

I/O(二)—— NIO

  1. 所有的Channel都是通过传统节点流的getChannel()获得

  2. Channel类似于传统的流对象,但二者的区别在于:

    1. Channel可以直接将指定的文件部分或全部直接映射成Buffer。
    2. 程序不能直接访问Channel中的数据(无论读、写),Channel只能与Buffer进行交互。
  3. map()方法:该方法用于将Channel中对应的部分映射成ByteBuffer

MappedByteBuffer map(MapMode mode, long position, long size)
四、字符集Charset
  1. 字符集用于解决二进制序列与字符之间的映射关系
  2. Charset对象的获取方法
Charset charset = Charset.forName("GBK");
  1. 获取到Charset对象后,可调用此对象的newDecoder()、newEncoder()这两个方法分别获得该字符集的解码器和编码器。
五、Java7的NIO.2
  1. 提供了Path类,优化了传统File类功能有限且所提供方法性能不高的缺陷。
  2. 提供了Files和Paths两个工具类
  3. 使用FileVisitor遍历文件和目录
public interface FileVisitor<T> {
	//访问子目录之前触发事件
    FileVisitResult preVisitDirectory(T dir, BasicFileAttributes attrs)
        throws IOException;
	//访问file文件时触发事件
    FileVisitResult visitFile(T file, BasicFileAttributes attrs)
        throws IOException;
	//访问文件失败时触发事件
    FileVisitResult visitFileFailed(T file, IOException exc)
        throws IOException;
	//访问子目录之后触发事件
    FileVisitResult postVisitDirectory(T dir, IOException exc)
        throws IOException;
}

以上四个方法都返回一个FileVisitResult对象,他是一个枚举类,代表后续行为

public enum FileVisitResult {
    //继续访问
    CONTINUE,
    //中止范围跟
    TERMINATE,
    //继续访问,但不访问该文件或跳过该目录的子目录树
    SKIP_SUBTREE,
    //继续访问,但不访问该文件或目录的兄弟文件或目录
    SKIP_SIBLINGS;
}
  1. 使用WatchService来监控文件变化
    NIO.2的Path类提供如下方法来监听文件系统的变化
    //用watcher监听变化。events参数指定要监听哪些类型的事件。
    WatchKey register(WatchService watcher, WatchEvent.Kind<?>... events)throws IOException;

	WatchKey register(WatchService watcher,WatchEvent.Kind<?>[] events,WatchEvent.Modifier... modifiers)
        throws IOException;

注册完成后,可调用WatchService的如下三个方法来获取变化事件

	//获取下一个WatchKey,如果没发生,则返回null
	WatchKey poll();
	//等待指定的时间,返回下一个WatchKey,如果一直没事件发生则返回null
    WatchKey poll(long timeout, TimeUnit unit) throws InterruptedException;
    //获取下一个WatchKey,如果没发生就一直等待
    WatchKey take() throws InterruptedException;
上一篇:Netty学习笔记之Java NIO编程


下一篇:TCP之JAVA通信