码迷,mamicode.com
首页 > 其他好文 > 详细

NIO 详解

时间:2019-09-07 12:26:23      阅读:112      评论:0      收藏:0      [点我收藏+]

标签:ati   void   string   读取数据   字节   server   import   异步   同步   

同步非阻塞

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 详解

标签:ati   void   string   读取数据   字节   server   import   异步   同步   

原文地址:https://www.cnblogs.com/loveer/p/11479887.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!