NIO 详解

Posted loveer

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NIO 详解相关的知识,希望对你有一定的参考价值。

同步非阻塞

NIO之所以是同步,是因为它的accept read write方法的内核I/O操作都会阻塞当前线程

Channel(通道)

Channel(通道):

    Channel是一个对象,可以通过它读取和写入数据。可以把它看做是IO中的流,不同的是:

        Channel是双向的(NIO面向缓冲区,双向传输),既可以读又可以写,而流是单向的(传统IO操作是面向流,单向传输)

        Channel可以进行异步的读写

        对Channel的读写必须通过buffer对象

        buffer负责存储数据,channel负责传输数据


在Java NIO中的Channel主要有如下几种类型:

    FileChannel:从文件读取数据的

    DatagramChannel:读写UDP网络协议数据

    SocketChannel:读写TCP网络协议数据

    ServerSocketChannel:可以监听TCP连接

Buffer(缓冲区)

Buffer是一个对象:

    它包含一些要写入或者读取Stream对象的。用于读写操作(put()存,get()取)。

    它包含四个属性:
        capacity(总容量)
        limit(当前可用容量)
        position(正在操作数据的位置)
        mark(标记当前position,可通过reset()恢复mark位置)

在NIO中,Buffer实质上是一个数组,通常是一个字节数据,但也可以是其他类型的数组。


使用 Buffer 读写数据一般遵循以下四个步骤:

    1.写入数据到 Buffer;

    2.调用 flip() 方法;

    3.从 Buffer 中读取数据;

    4.调用 clear() 方法或者 compact() 方法。

当向 Buffer 写入数据时,Buffer 会记录下写了多少数据。
一旦要读取数据,需要通过 flip() 方法将 Buffer 从写模式切换到读模式。
在读模式下,可以读取之前写入到 Buffer 的所有数据。

一旦读完了所有的数据,就需要清空缓冲区,让它可以再次被写入。有两种方式能清空缓冲区:

    调用 clear() 或 compact() 方法。

    clear() 方法会清空整个缓冲区。

    compact() 方法只会清除已经读过的数据。任何未读的数据都被移到缓冲区的起始处,新写入的数据将放到缓冲区未读数据的后面。


Buffer主要有如下几种:

    ByteBuffer
    CharBuffer
    DoubleBuffer
    FloatBuffer
    IntBuffer
    LongBuffer
    ShortBuffer

简单应用

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class CopyFile {
    public static void copyFile(String src, String dst) throws IOException {
        
        //源文件输入流
        FileInputStream fi = new FileInputStream(new File(src));
        //目标文件输出流
        FileOutputStream fo = new FileOutputStream(new File(dst));

        //获得传输通道channel
        FileChannel inChannel = fi.getChannel();
        FileChannel outChannel = fo.getChannel();

        //获得容器buffer
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        while (true) {
            //判断是否读完文件:阻塞式
            int eof = inChannel.read(buffer);
            if (eof == -1) {
                break;
            }
            //重设一下buffer的limit=position,position=0
            buffer.flip();

            //开始写
            outChannel.write(buffer);

            //写完要重置buffer,重设position=0,limit=capacity
            buffer.clear();
        }
        inChannel.close();
        outChannel.close();
        fi.close();
        fo.close();
    }
}

以上是关于NIO 详解的主要内容,如果未能解决你的问题,请参考以下文章

Java NIO 详解

java基础知识--NIO详解及实战

NIO学习之NIO概述和FileChannel详解

Java网络编程和NIO详解8:浅析mmap和Direct Buffer

详解 同步异步阻塞非阻塞 与 BIO NIO AIO区别多路复用

tomcat趣谈之NIO源码详解(这回你总该懂了吧)