Java NIO原理及使用

运行环境:idea2018,jdk11

简述

1、比较

IO

NIO

数据处理

字节或字符流(stream)

块(channel)

方向

单向(InputStream/OutputStream)

双向(读写)

2、NIO(Non-blocking I/O),非阻塞IO,也可以理解为新IO(new I/O)。相对于传统的IO以字节或字符或单位传输,NIO以数据块的方式批量传输。突出的有点就是快速和简单,在网络传输中优势明显。

3、NIO具有双向读写功能,支持一个缓存中同时包含读写功能。

4、@since jdk1.4

通道Channel

NIO是在IO的基础上集成出来的,而通道channel类似I/O中的流,通过它进行读写操作,且方向是双向的。

通道在包java.nio.channels下,主要有以下4种类型


功能

channel for

FileChannel

从文件中读写数据

reading, writing, mapping, and manipulating a file.

DatagramChannel

通过 UDP 读写网络中数据

datagram-oriented sockets.

SocketChannel

通过 TCP 读写网络中数据

stream-oriented connecting sockets

ServerSocketChannel

监听新进来的TCP 连接

stream-oriented listening sockets

缓冲区

IO中缓冲充当装饰类,非必须。而NIO中,一个通道的所有数据必须先放到缓冲区,再进行读写数据,不能直接操作通道进行读写。底层是一个数组。

读写演示

1、为通道新建一个8个字节缓冲区,则最大容量capacity为8,还可以读写的字节数limit也为8,

指针posistion指向下一个待读写的位置,即当前已经读写的字节数。



2、从输入通道中读取 4个字节数据写入缓冲区,posittion指针指向下一个位置4,limit不变。



3、将缓冲区写入输出通道,先调用flip(),该方法flip缓存,limit设置到当前position位置,并且limit标记到4,然后position设置为0。



4、从缓冲区中取 4 个字节到输出缓冲中,此时 position 设为 4。



5、最后需要调用 clear() 方法,该方法清空缓存,position设置到0,limit设置到capacity。



代码演示

使用nio,从d盘中的aaa.txt文件拷贝到e盘。

public class TestNIO {

    @Test
    public void testCopy(){
        try {
            // 创建输入流
            FileInputStream in = new FileInputStream("D:\\aaa.txt");
            // 创建输入通道
            FileChannel inChannel = in.getChannel();
            // 创建输出流
            FileOutputStream out = new FileOutputStream("E:\\aaa.txt");
            // 创建通道
            FileChannel outChannel = out.getChannel();
            // 创建缓存,大小1024字节
            ByteBuffer buffer = ByteBuffer.allocateDirect(1024);
            // 循环读写
            while (true){
                // 从通道读取序列的自接到给定缓冲区,更新position位置
                int read = inChannel.read(buffer);            
                // 全部读完退出
                if (read==-1){
                    break;
                }   
                // flip缓存,position回到0
                buffer.flip();
                // 缓冲区写道输出通道
                outChannel.write(buffer);
                // 清空,limit回到capacity
                buffer.clear();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
复制代码

拷贝完成!