美文网首页
NIO 原理分析、Okio 简单使用

NIO 原理分析、Okio 简单使用

作者: z白依 | 来源:发表于2020-01-06 22:41 被阅读0次

    NIO


    与 传统IO 的区别
    • 传统IO:用的是插管道(单向管道 stream)。可以先了解一下 传统IO Java I/O 原理分析
    • NIO:也是用的插管道(双向管道 channel)。NIO 有非阻塞式的支持,而不是非阻塞式的,而且默认是阻塞式的。其中网络交互支持非阻塞式(默认是阻塞式的),文件交互只能是阻塞式的。


      nio
    Buffer

    在 NIO 中需强制使用 buffer,不用都不行。它的 buffer 可以被操作,操作的是 buffer 本身而不是管道。而且 buffer 不好用,为什么这么说呢,来看一下:

    try {
        // 传入的参数 name:文件名,mode:模式“r”表示 read,其他还有 rw、rws、rwd
        RandomAccessFile file = new RandomAccessFile("./new.txt", "r");
        // 管道 channel
        FileChannel channel = file.getChannel();
        // 获取 buffer
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
        // buffer 视角,buffer 是内,channel 是外
        channel.read(byteBuffer);
        // ①
        byteBuffer.limit(byteBuffer.position());
        byteBuffer.position(0);
        // 打印文件中的内容
        System.out.println(Charset.defaultCharset().decode(byteBuffer));
        // ②
        byteBuffer.limit(byteBuffer.capacity());
        byteBuffer.position(0);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    

    首先要了解三个东西:

    • capacity:容量。buffer的容量,就是上面代码中的1024
    • limit:限制。指的是读或写的最大范围在哪。
    • position: 位置。读和写都是用它做指针。读到第几个了,写到第几个了

    它们有什么用,到底是什么意思呢?


    buffer1

    如上图:这是初始状态,position = 0 指向第一个位置,capacity是总容量大小;limit 意思是: position 最多可以达到的大小,初始的时候,limit = capacity,也就是说做多可以读1024个大小的数据(buffer视角输入所以是读)。

    这么说可能理解不了,举个例子:


    在这里插入图片描述

    上图是buffer读了ABCD之后的状态:position会指向4这个位置,意思是读的下一个就是4(buffer视角,输入)。

    如果这个时候直接操作 buffer,(内存视角,输入)从buffer读数据到内存并打印,就会有问题。所以必须要设置position和limit,如上面代码中①,先把limit = position,记录限制的大小,然后position = 0。这样才能正常的从buffer读数据到内存中。

    下图就是执行了①之后的模型:


    buffer3

    当读完之后,position 就会和 limit 一样指向4这个位置了。就不画图了。最后在读完之后要重置position 和 limit,就是②所做的事了,buffer的状态就会回到初始状态。

    ① 和 ② 都是挺常见的操作,buffer 也提供了这样的功能:

    // ① 翻页
    byteBuffer.flip();
    // ② 清除
    byteBuffer.clear();
    

    Okio


    介绍
    • 也是基于插管,而且是单向的
      • 输入源:Source
      • 输出目标:Sink (水槽,往里面装水用的)
    • 也支持 buffer,
      • 不强制使用
      • 也可以对 buffer 进行操作
    使用

    简单使用:

    try (BufferedSource source = Okio.buffer(Okio.source(new File("./new.txt")))) {
        System.out.println(source.readUtf8());
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    

    使用 buffer:

    try (BufferedSource source = Okio.buffer(Okio.source(new File("./new.txt")))) {
        // 创建 buffer
        Buffer buffer = new Buffer();
        // 读数据到 buffer(buffer视角,buffer 是内,文件是外)
        source.read(buffer, 1024);
        // 读数据到内存(内存视角,内存是内,buffer 是外)
        System.out.println(buffer.readUtf8Line());
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    

    另外 buffer 还有一个比较灵活比较方便的功能:可以往 buffer 上面插管子 InputStream,OutputStream。这样就可以引入传统 IO,把 Okio 和传统 IO 合起来用。如果老项目老代码用的是传统 IO,而 Okio 也会用到,这样就可以让它们做对接。怎么对接呢?如下:

    // Okio 的 buffer
    Buffer buffer = new Buffer();
    OutputStream outputStream = buffer.outputStream();
    InputStream inputStream = buffer.inputStream();
    

    总结


    本文主要介绍了NIO,Okio。

    NIO和传统IO 的对比,什么情况下才能用非阻塞式。buffer 的原理,该怎么用。

    Okio 的介绍和使用。

    最后再简单说一下AIO,BIO。

    • BIO:就是有的人给传统IO起的名字。B:blocking 阻塞,但是NIO在很多情况下其实也是阻塞式的。。。
    • AIO:Asynchronous IO,异步IO。Java7新出的一套带有回调功能的异步IO,跟多线程回调一样用起来比较方便的那种把工作放到后台的IO。

    相关文章

      网友评论

          本文标题:NIO 原理分析、Okio 简单使用

          本文链接:https://www.haomeiwen.com/subject/poelactx.html