Netty学习 2、通道(Channel)

通道(Channel)

一、通道(Channel)

通道(Channel)是NIO用来传输数据的。和流类似,只不过有很大的区别

区别:

  • ​ 通道用来传输的是数据块,也就是Buffer。而流用来传输字节的
  • ​ 通道可以同时进行读写,而流只能读或者只能写
  • ​ 通道可以实现异步读写数据
  • ​ 通道可以从缓冲读数据,也可以写数据到缓冲
二、常用的通道类
类名作用
FileChannel用于文件的数据读写
DatagramChannel用于UDP的数据读写
ServerSocketChannel和SocketChannel用于TCP的数据读写
三、FileChannel实列
package com.dashu.nio;


import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.CharacterCodingException;
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;
import java.util.Map;
import java.util.Set;

/**
 * 在NIO中,缓冲区就像高铁,通道就是高铁路,人就是数据。
 * 人坐高铁,高铁通过高铁路从贵阳到北京
 * 缓冲区存数据,通道传输缓冲区
 * <p>
 * 一、通道(Channel)
 * 用于源节点与目标节点的连接。
 * 在Java NIO中负责缓冲区中数据的传输
 * Channel本身不存储数据,因此需要配合缓冲区进行传输
 * <p>
 * 二、通道的主要实现类
 * java.nio.channels.Channel接口
 * |--FileChannel
 * |--SocketChannel
 * |--ServerSocketChannel
 * |--DatagramChannel
 * <p>
 * 三、获取通道
 * 1、Java针对支持通道的类提供了getChannel()方法
 * 本地IO:
 * FileInputStream/FileOutputStream
 * RandomAccessFile
 * <p>
 * 网络IO:
 * Socket
 * ServerSocket
 * DatagramSocket
 * <p>
 * 2、在JDK1.7中的NIO.2针对各个通道提供了静态方法open()
 * 3、在JDK1.7中的NIO.2的Feles工具类的newByteChannel()
 * <p>
 * 四、通道之间的数据传输
 * transferFrom()
 * transferTo()
 * <p>
 * 五、分散(Scatter)与聚集(Gather)
 * 分散读取(Scattering Reads):将通道中的数据分散到多个缓冲区中
 * 聚集写入(Gathering Writes):将多个缓冲去中的数据聚集到通道中
 * <p>
 * 六、字符集:Charset
 * 编码:字符串 -> 字节数组
 * 解码:字节数组 -> 字符串
 */

public class NioChannel {



    public static void main(String[] args) throws CharacterCodingException {
        NioChannel nioChannel = new NioChannel();
    }

   



   


    /**
     * 分散读取,和聚集写入
     */
    public void test04() {

        //输入文件
        RandomAccessFile inRandomAccessFile = null;
        //输入文件通道
        FileChannel inFileChannel = null;

        //输出通道
        RandomAccessFile outRandomAccessFile = null;
        //输出文件通道
        FileChannel outFileChannel = null;


        try {

            //创建输入文件
            inRandomAccessFile = new RandomAccessFile("d:/a.txt", "rw");

            //创建输入通道
            inFileChannel = inRandomAccessFile.getChannel();

            //缓冲区1
            ByteBuffer byteBuffer1 = ByteBuffer.allocate(100);
            //缓冲区2
            ByteBuffer byteBuffer2 = ByteBuffer.allocate(100);

            //缓冲区数组
            ByteBuffer[] byteBuffers = {byteBuffer1, byteBuffer2};

            //将输入通道中的数据写到缓冲区数组
            inFileChannel.read(byteBuffers);

            //切换缓冲区数组中缓冲区的模式:读
            for (ByteBuffer byteBuffer : byteBuffers) {
                byteBuffer.flip();
            }

            //分别打印缓冲区中的数据
            System.out.println(new String(byteBuffers[0].array(), 0, byteBuffers[0].limit()));
            System.out.println("-----------");
            System.out.println(new String(byteBuffers[1].array(), 0, byteBuffers[1].limit()));


            //创建输出文件
            outRandomAccessFile = new RandomAccessFile("d:/a2.txt", "rw");
            //创建输出通道
            outFileChannel = outRandomAccessFile.getChannel();
            //将缓冲区数组的数据写到输出通道
            outFileChannel.write(byteBuffers);

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //通道和文件输入流关闭关闭

            if (outFileChannel != null) {
                try {
                    outFileChannel.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }


            if (outRandomAccessFile != null) {
                try {
                    outRandomAccessFile.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }


            if (inFileChannel != null) {
                try {
                    inFileChannel.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }


            if (inRandomAccessFile != null) {
                try {
                    inRandomAccessFile.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

    }


    /**
     * 通道之间的数据传输
     */
    public void test03() {
        //获取当前时间毫秒
        long start = System.currentTimeMillis();

        //获取文件输入通道
        FileChannel inChannel = null;

        //获取文件输出通道
        FileChannel outChannel = null;


        try {

            //创建文件输入通道(StandardOpenOption.READ:读)
            inChannel = FileChannel.open(Paths.get(""), StandardOpenOption.READ);

            //创建文件输出通道(StandardOpenOption.WRITE:写, StandardOpenOption.READ:读, StandardOpenOption.CREATE:文件不存在创建,文件存在覆盖)
            outChannel = FileChannel.open(Paths.get(""), StandardOpenOption.WRITE, StandardOpenOption.READ, StandardOpenOption.CREATE);

            //将输入文件通道的输据转移到输出文件通道
            inChannel.transferTo(0, inChannel.size(), outChannel);

            //将输入文件通道的输据转移到输出文件通道
            outChannel.transferFrom(inChannel, 0, inChannel.size());

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //通道关闭

            if (outChannel != null) {
                try {
                    outChannel.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }


            if (inChannel != null) {
                try {
                    inChannel.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        //获取当前时间毫秒
        long end = System.currentTimeMillis();
        //输出
        System.out.println("耗时:" + (end - start));

    }

    /**
     * 利用通道完成文件的复制(直接缓冲区)
     */
    public void test02() {
        //获取当前时间毫秒
        long start = System.currentTimeMillis();

        //文件输入通道
        FileChannel inChannel = null;

        //文件输出通道
        FileChannel outChannel = null;


        try {

            // 输入通道(StandardOpenOption.READ:读)
            inChannel = FileChannel.open(Paths.get("d:/a.txt"), StandardOpenOption.READ);

            // 输入通道(StandardOpenOption.WRITE:写, StandardOpenOption.READ:读, StandardOpenOption.CREATE:文件不存在创建,文件存在覆盖)
            outChannel = FileChannel.open(Paths.get("d:/a3.txt"), StandardOpenOption.WRITE, StandardOpenOption.READ, StandardOpenOption.CREATE);

            //通过输入通道获取输入Buffer
            MappedByteBuffer inMappedByteBuffer = inChannel.map(FileChannel.MapMode.READ_ONLY, 0, inChannel.size());

            //通过输出通道获取输出Buffer
            MappedByteBuffer outMappedByteBuffer = outChannel.map(FileChannel.MapMode.READ_WRITE, 0, inChannel.size());

            //创建byte数组
            byte[] dst = new byte[inMappedByteBuffer.limit()];

            //获取输入Buffer的数据保存到byte数组
            inMappedByteBuffer.get(dst);

            //将byte数组的数据保存到输出Buffer
            outMappedByteBuffer.put(dst);

        } catch (Exception e) {
            //异常抛出
            e.printStackTrace();
        } finally {

            //通道关闭

            if (outChannel != null) {
                try {
                    outChannel.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }


            if (inChannel != null) {
                try {
                    inChannel.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }


        //获取当前时间毫秒
        long end = System.currentTimeMillis();
        //输出
        System.out.println("耗时:" + (end - start));
    }

    /**
     * 利用通道完成文件的复制(非直接缓冲区)
     */
    public void test01() {
        //获取当前时间毫秒
        long start = System.currentTimeMillis();

        //文件输入流
        FileInputStream fileInputStream = null;

        //文件输出流
        FileOutputStream fileOutputStream = null;

        //文件输入通道
        FileChannel inChannel = null;

        //文件输出通道
        FileChannel outChannel = null;


        try {

            //输入文件
            fileInputStream = new FileInputStream("d:/a.txt");

            //输出文件
            fileOutputStream = new FileOutputStream("d:/a2.txt");

            //输入通道
            inChannel = fileInputStream.getChannel();

            //输出通道
            outChannel = fileOutputStream.getChannel();

            //创建缓存区
            ByteBuffer byteBuffer = ByteBuffer.allocate(1024);

            //循环将”输入通道“中的数据读取到”缓存区“,然后将”缓存区“中的数据写入到”输出通道“
            while (true) {

                //先清空缓存区
                byteBuffer.clear();

                //将”输入通道“中的数据读取(存入)到”缓存区“
                int read = inChannel.read(byteBuffer);

                //判断”输入通道“中的数据是否读取完,读取完,退出循环
                if (read == -1) {
                    break;
                }

                //切换”缓存区“模式:读
                byteBuffer.flip();

                //将”缓存区“中的数据写到(存入)”输出通道“
                outChannel.write(byteBuffer);

            }
        } catch (Exception e) {
            //异常抛出
            e.printStackTrace();
        } finally {

            //关闭通道和流

            if (outChannel != null) {
                try {
                    outChannel.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }

            if (inChannel != null) {
                try {
                    inChannel.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }

            if (fileOutputStream != null) {
                try {
                    fileOutputStream.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }

            if (fileInputStream != null) {
                try {
                    fileInputStream.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }
        }

        //获取当前时间毫秒
        long end = System.currentTimeMillis();
        //输出
        System.out.println("耗时:" + (end - start));
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大树下躲雨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值