缓冲区的搬运工——通道 Channel

x33g5p2x  于2022-05-18 转载在 其他  
字(2.9k)|赞(0)|评价(0)|浏览(298)

一 点睛

通道用于数据的双向传输,即一个通道既可以用于读数据,又可以用于写数据。注意,这点不同于 I/O 中的 Stream,Stream 是单向的(只能是输入流或输出流)。

在 NIO 中,就是使用“缓冲区+通道”进行数据的传输。具体地讲,就是使用通道对缓冲区、文件或套接字进行数据传输。

可以把缓冲区理解为“池塘”,把通道理解为“排水管”。

NIO 中的 Channel(通道)是一个接口,有以下几种常见的实现类。

  • FileChannel
  • SocketChannel
  • ServerSocketChannel
  • DatagramChannel

如果药获取 Channel 对象,可以使用下表。

| <br>FileInputStream<br><br>FileOutputStream<br><br>RandomAccessFile<br> | <br>本地 I/O 类。这些类中都提供了 FileChannel getChannel() 方法,可以用于获取 FileChannel 对象。<br> |
| <br>Socket<br><br>ServerSocket<br><br>DatagramSocket<br> | <br>网络 I/O 类。这些类提供了 XXXChannel getChannel() 方法,可以用于获取不同类型的 Channel 对象。<br> |
| <br>FileChannel 等各个 Channel 实现类<br> | <br>Channel 实现类中,都提供了用于获取 Channel 对象的 open() 方法。例如,FileChannel 类中的 open() 方法:public static FileChannel open(Path path, OpenOption... options) throws IOException<br> |
| <br>Files<br> | <br>public static SeekableByteChannel newByteChannel(Path path, OpenOption... options)<br> |

二 缓冲区文件复制

1 代码

package nio;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.Pipe;
import java.nio.charset.CharacterCodingException;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

public class NIODemo {
    // 使用非直接缓冲区复制文件
    public static void test2() throws IOException {
        long start = System.currentTimeMillis();
        FileInputStream input = new FileInputStream("g:\\navicat.chm");
        FileOutputStream out = new FileOutputStream("g:\\navicat_copy1.chm");
        // 获取通道
        FileChannel inChannel = input.getChannel();
        FileChannel outChannel = out.getChannel();
        ByteBuffer buffer = ByteBuffer.allocate(1024);

        while (inChannel.read(buffer) != -1) {
            buffer.flip();
            outChannel.write(buffer);
            buffer.clear();
        }
        if (outChannel != null) outChannel.close();
        if (inChannel != null) inChannel.close();
        if (out != null) out.close();
        if (input != null) input.close();
        long end = System.currentTimeMillis();
        System.out.println("复制操作消耗的时间(毫秒):" + (end - start));
    }

    // 使用直接缓冲区复制文件
    public static void test2_2() throws IOException {
        long start = System.currentTimeMillis();
        FileInputStream input = new FileInputStream("g:\\navicat.chm");
        FileOutputStream out = new FileOutputStream("g:\\navicat_copy2.chm");
        // 获取通道
        FileChannel inChannel = input.getChannel();
        FileChannel outChannel = out.getChannel();
        ByteBuffer buffer = ByteBuffer.allocateDirect(1024);

        while (inChannel.read(buffer) != -1) {
            buffer.flip();
            outChannel.write(buffer);
            buffer.clear();
        }
        if (outChannel != null) outChannel.close();
        if (inChannel != null) inChannel.close();
        if (out != null) out.close();
        if (input != null) input.close();
        long end = System.currentTimeMillis();
        System.out.println("复制操作消耗的时间(毫秒):" + (end - start));
    }

    public static void main(String[] args) throws IOException {
        test2();
        System.out.println("--------------------------");
        test2_2();
    }
}

2 测试

复制操作消耗的时间(毫秒):162


复制操作消耗的时间(毫秒):137

相关文章