zoukankan      html  css  js  c++  java
  • Java NIO -2

    NIO

    http://www.cnblogs.com/puyangsky/p/5840873.html

    --

    操作系统与 Java 基于流的 I/O模型有些不匹配。操作系统要移动的是大块数据(缓冲区),这往往是在硬件直接存储器存取( DMA)的协助下完成的。而 JVM 的 I/O 类喜欢操作小块数据——单个字节、几行文本。结果,操作系统送来整缓冲区的数据, java.io 的流数据类再花大量时间把它们拆成小块,往往拷贝一个小块就要往返于几层对象。操作系统喜欢整卡车地运来数据, java.io 类则喜欢一铲子一铲子地加工数据。有了 NIO,就可以轻松地把一卡车数据备份到您能直接使用的地方( ByteBuffer 对象)。但是Java里的RandomAccessFile类是比较接近操作系统的方式。

    Java NIO主要依赖的组件有三个:缓冲区Buffer、通道Channel和选择器Selector。

    2.1 缓冲区(Buffer)

    Buffer家族主要有这么些个成员,根据类名也大概能猜到它们的用处,用的最多的是ByteBuffer,在下面的例子中也会主要用到它。

    2.1.1 缓冲区属性

    容量(capacity):缓冲区的最大大小

    上界(limit):缓冲区当前的大小

    位置(position):下一个要读写的位置,由get()和put()更新

    标记(mark):备忘位置,由mark()来指定mark = position,由reset()来指定position=mark

    它们之间的大小关系:

    0 <= mark <= position <= limit <= capacity

    Buffer/ ByteBuffer 源代码

    public final int remaining()
    {
    return this.limit - this.position;
    }

    public final boolean hasRemaining()
    {
    return this.position < this.limit;
    }

    public final Buffer flip()
    {
    this.limit = this.position;
    this.position = 0;
    this.mark = -1;
    return this;
    }

    public final Buffer clear()
    {
    this.position = 0;
    this.limit = this.capacity;
    this.mark = -1;
    return this;
    }

    2.2 通道(Channel)

    开始我不是很理解Channel这个东西为什么要存在,看了书才慢慢明白,缓冲区为我们装载了数据,但是数据的写入和读取并不能直接进行read()和write()这样的系统调用,而是JVM为我们提供了一层对系统调用的封装。而Channel可以用最小的开销来访问操作系统本身的IO服务,这就是为什么要有Channel的原因。

    2.2.2.1 打开

    FileChannel只能通过工厂方法来实例化,那就是调用RandomAccessFile、FileInputStream和FileOutputStream的getChannel()方法。如:

    RandomAccessFile file = new RandomAccessFile("a.txt", "r");
    FileChannel fc = file.getChannel();

     
    读取文件的整个过程相比原生的I/O方法还是略显麻烦,但是我们如果把数据看成一堆煤矿,把ByteBuffer看成装煤的矿车,而FileChannel看成是运煤的矿道,那么上面的过程就演变成了:先打通一条矿道,然后把煤矿装在小车里运出来。形象的记忆更利于理解这个过程。

     同样考虑一下形象化的过程:我们首先把煤矿装入小车(buffer.put()),并打开一条通往矿山的矿道(FileOutputStream.getChannel()),接着把煤矿运输进去(FileChannel.write(buffer))。还是很容易理解的吧

  • 相关阅读:
    bash 中 () {} [] [[]] (()) 的解释
    正则表达式速查笔记
    Makefile速查笔记
    gflags 编译动态库
    在Win10上运行ESXI-Comstomer
    GNU g++常用编译选项用法
    C++标准转换运算符reinterpret_cast
    BZOJ 3211: 花神游历各国【线段树区间开方问题】
    BZOJ 1597: [Usaco2008 Mar]土地购买【斜率优化+凸包维护】
    BZOJ 1046: [HAOI2007]上升序列【贪心+二分状态+dp+递归】
  • 原文地址:https://www.cnblogs.com/kakaisgood/p/6651471.html
Copyright © 2011-2022 走看看