1.首先我们先说一说什么是NIO:

  • NIO是JDK1.4 New IO JDK1.7 在 nio包下又增加了一些API
  • NIO 与原来的 IO 有同样的作用和目的,但是使用的方式完全不同, NIO 支持面向缓冲区的、基于通道的 IO 操作。 NIO 将以更加高效的方式进行文件的读写

在这里插入图片描述

在这里插入图片描述
2.通道和缓冲区

Java NIO 系统的核心在于:通道 (Channel) 和缓冲区(Buffer) 。通道表示打开到 IO 设备 ( 例如:文件、套接字 ) 的连接。若需要使用 NIO 系统,需要获取用于连接 IO 设备的通道以及用于容纳数据的缓冲区。然后操作缓冲区,对数据进行处理,简单的说Channel负责传输,Buffer负责存储

  • 缓冲区

A. 一个用于特定基本数据类型的容器。由 java.nio 包定义的,所有缓冲区都是 Buffer 抽 象类的子类。
B. Java NIO中的 Buffer 主要用于与 NIO 通道进行交互,数据是从通道读入缓冲区,从缓冲区写
C. Buffer 就像一个数组,可以保存多个相同类型的数据。根据数据类型不同 (boolean 除外 ) ,有以下 Buffer 常用子类:

  • ByteBuffer

  • CharBuffer

  • ShortBuffer

  • IntBuffer

  • LongBuffer

  • FloatBuffer

  • DoubleBuffer
    上述 Buffer 类 他们都采用相似的方法进行管理数据,只是各自管理的数据类型不同而已。都是通过如下方法获取一个 Buffer对象:

    static XxxBuffer allocate(int capacity) : 创建一个容量为 capacity 的 XxxBuffer 对象
    

缓冲区的基本属性

D.Buffer 中的重要概念:

  • 容量 (capacity) : 表示 Buffer 最大数据容量,缓冲区容量不能为负,并且创
    建后不能更改。

  • 限制 (limit) : 第一个不应该读取或写入的数据的索引,即位于 limit 后的数据
    不可读写。缓冲区的限制不能为负,并且不能大于其容量。

  • 位置 (position) : 下一个要读取或写入的数据的索引。缓冲区的位置不能为
    负,并且不能大于其限制

  • 标记 (mark) 与重置 (reset) : 标记是一个索引,通过 Buffer 中的 mark() 方法
    指定 Buffer 中一个特定的 position ,之后可以通过调用 reset() 方法恢复到这
    个 position.

在这里插入图片描述
- Buffer中常用的方法
在这里插入图片描述
- Buffer 所有子类提供了两个用于数据操作的方法: get()与put()方法

  • 获取Buffer中的数据:
    get() :读取单个字节
    get(byte[] dst) :批量读取多个字节到 dst 中
    get(int index) :读取指定索引位置的字节 ( 不会移动position)
  • 放入数据到 Buffer 中
    put(byte b) :将给定单个字节写入缓冲区的当前位置
    put(byte[] src) :将 src 中的字节写入缓冲区的当前位置
    put(int index, byte b) :将指定字节写入缓冲区的索引位置 ( 不会移动 position)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 通道
    A. 首先通道是由 java.nio.channels 包定义的。 Channel 表示 IO 源与目标打开的连接。Channel 类似于传统的“流”。只不过 Channel本身不能直接访问数据, Channel 只能与Buffer 进行交互。
    B.Java 为 Channel 接口提供的最主要实现类如下:
    a. FileChannel :用于读取、写入、映射和操作文件的通道。
    b. DatagramChannel :通过 UDP 读写网络中的数据通道。
    c. SocketChannel :通过 TCP 读写网络中的数据
    d. ServerSocketChannel :可以监听新进来的 TCP 连接,对每一个新进来的连接都会创建一个 SocketChannel 。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    C.获取通道的几种方式
 //通道:获取通道的方式1
FileInputStream in = new FileInputStream("a.txt");
FileOutputStream out = new FileOutputStream("aa.txt");
// FileChannel 本地的文件传输通道
FileChannel inChannel = in.getChannel();
FileChannel outChannel = out.getChannel();
//获取通道方式2
//FileChannel inChannel = FileChannel.open(Paths.get("a.txt"), StandardOpenOption.READ);
//FileChannel outChannel = FileChannel.open(Paths.get("bb.txt"), StandardOpenOption.WRITE, StandardOpenOption.CREATE);
//获取通道的方式三  JDK1.7 提供了一个类 Files
//SeekableByteChannel inChannel = Files.newByteChannel(Paths.get("a.txt"), StandardOpenOption.READ);
//SeekableByteChannel outChannel = Files.newByteChannel(Paths.get("cc.txt"), StandardOpenOption.WRITE, StandardOpenOption.CREATE);  
//获取通道的方式4 JDk1.7 有个 Channels
    ReadableByteChannel inChannel = Channels.newChannel(new FileInputStream("a.txt"));
    WritableByteChannel outChannel = Channels.newChannel(new FileOutputStream("dd.txt"));

    ByteBuffer byteBuffer = ByteBuffer.allocateDirect(1024);
    while (inChannel.read(byteBuffer) != -1) {
        byteBuffer.flip();//切换到读取模式
        outChannel.write(byteBuffer);
        byteBuffer.clear();
    }

    //in.close();
    //out.close();
    inChannel.close();
    outChannel.close();

D.通道的数据传输
将 Buffer 中数据写入 Channel例如:
int
从 Channel 读取数据到 Buffer例如:
在这里插入图片描述

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐