NIO入门与基本使用

感谢易学好文。以下均来自https://www.e-learn.cn/content/qita/674902 文章内容的学习与实践。

package test.nio;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

/**
 * *
 * * 一、通道(Channel):用于源节点与目标节点的连接。在 Java NIO 中负责缓冲区中数据的传输。Channel 本身不存储数据,因此需要配合缓冲区进行传输。
 * *
 * * 二、通道的主要实现类
 * *  java.nio.channels.Channel 接口:
 * *      |--FileChannel:用于读取、写入、映射和操作文件的通道
 * *      |--SocketChannel:通过TCP读写网络中的数据
 * *      |--ServerSocketChannel:可以监听新进来的TCP连接,对每一个新进来的连接都会创建一个 SocketChannel
 * *      |--DatagramChannel:通过UDP读写网络中的数据通道
 * *
 * * 三、获取通道
 * * 1. Java 针对支持通道的类提供了 getChannel() 方法
 * *      本地 IO:
 * *      FileInputStream/FileOutputStream
 * *      RandomAccessFile
 * *
 * *      网络IO:
 * *      Socket
 * *      ServerSocket
 * *      DatagramSocket
 * *
 * * 2. 在 JDK 1.7 中的 NIO.2 针对各个通道提供了静态方法 open()
 * * 3. 在 JDK 1.7 中的 NIO.2 的 Files 工具类的 newByteChannel()
 * *
 * * 四、通道之间的数据传输
 * * transferFrom()
 * * transferTo()
 * *
 * * 五、分散(Scatter)与聚集(Gather)
 * * 分散读取(Scattering Reads):将通道中的数据分散到多个缓冲区中
 * * 聚集写入(Gathering Writes):将多个缓冲区中的数据聚集到通道中
 * *
 * * 六、字符集:Charset
 * * 编码:字符串 -> 字节数组
 * * 解码:字节数组  -> 字符串
 */
public class TestChannel {
    public static void main(String[] args) {

    }

    /**
     * 利用通道完成文件的复制(非直接缓冲区)
     */
    public static void noDirect() {

        try (FileInputStream fis = new FileInputStream("D:" + File.separator + "1.png");
             FileOutputStream fos = new FileOutputStream("D:" + File.separator + "2.png");
             FileChannel inChannel = fis.getChannel();
             FileChannel outChannel = fos.getChannel()
        ) {
            ByteBuffer buf = ByteBuffer.allocate(1024);
            while (inChannel.read(buf) != -1) {
                buf.flip();
                outChannel.write(buf);
                buf.clear();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 使用直接缓冲区完成文件的复制(内存映射文件)
     */
    public static void direct() {
        try (FileChannel inChannel = FileChannel.open(Paths.get("d:/1.png"), StandardOpenOption.READ);
             FileChannel outChannel = FileChannel.open(Paths.get("d:/3.png"), StandardOpenOption.WRITE, StandardOpenOption.READ, StandardOpenOption.CREATE)
        ) {
            //内存映射文件
            MappedByteBuffer inMappedBuf = inChannel.map(FileChannel.MapMode.READ_ONLY, 0, inChannel.size());
            MappedByteBuffer outMappedBuf = outChannel.map(FileChannel.MapMode.READ_WRITE, 0, inChannel.size());
            //直接对缓冲区进行读写操作
            byte[] dst = new byte[inMappedBuf.limit()];
            inMappedBuf.get(dst);
            outMappedBuf.put(dst);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 通道之间的数据传输(直接缓冲区)
     */
    public static void transByChannel() {
        try (FileChannel inChannel = FileChannel.open(Paths.get("D:/1.png"), StandardOpenOption.READ);
             FileChannel outChannel = FileChannel.open(Paths.get("D:/4.png"), StandardOpenOption.WRITE, StandardOpenOption.READ, StandardOpenOption.CREATE)) {
            ;
            long position = 0L;//定义传输位置
            long count = inChannel.size();//最对传输字节数
            //将数据从源通道传递到另一个通道
            outChannel.transferFrom(inChannel, position, count);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 分散和聚集
     */
    public static void scatterAndGather() {
        try (RandomAccessFile raf1 = new RandomAccessFile("D:/1.txt", "rw");
             FileChannel channel1 = raf1.getChannel();
             RandomAccessFile raf2 = new RandomAccessFile("D:/2.txt", "rw");
             FileChannel channel2 = raf2.getChannel()
        ) {
            ByteBuffer buf1 = ByteBuffer.allocate(100);
            ByteBuffer buf2 = ByteBuffer.allocate(1024);

            //分散读取
            ByteBuffer[] bufs = {buf1, buf2};
            channel1.read(bufs);

            for (ByteBuffer buffer : bufs) {
                buffer.flip();
            }

            System.out.println(new String(bufs[0].array(), 0, bufs[0].limit()));
            System.out.println("-------------");
            System.out.println(new String(bufs[1].array(), 0, bufs[1].limit()));

            //聚集写入
            channel2.write(bufs);

        } catch (Exception e) {

        }
    }

    public static void charSetTest() throws IOException {
        Charset cs1 = Charset.forName("GBK");

        //获取编码器
        CharsetEncoder ce = cs1.newEncoder();

        //获取解码器
        CharsetDecoder cd = cs1.newDecoder();

        CharBuffer cBuf = CharBuffer.allocate(1024);
        cBuf.put("你很牛逼!");
        cBuf.flip();

        //编码
        ByteBuffer bBuf = ce.encode(cBuf);

        for (int i = 0; i < 10; i++) {
            System.out.println(bBuf.get());
        }

        //解码
        bBuf.flip();
        CharBuffer cBuf2 = cd.decode(bBuf);
        System.out.println(cBuf2.toString());

    }
}

猜你喜欢

转载自blog.csdn.net/liyuxing6639801/article/details/80707464