• Netty(三)- NIO三大组件之Channel


    一、Channel 基本介绍

    1. NIO的通道类似于流,但有些区别如下:
      通道可以同时进行读写,而流只能读或者只能写;
      通道可以实现异步读写数据;
      通道可以从缓冲区读数据,也可以写数据到缓冲区;
      在这里插入图片描述
    2. BIO 中的 stream 是单向的,例如 FileInputStream 对象只能进行读取数据的操作,而 NIO 中的Channel(通道)是双向的,可以读操作,也可以写操作 ;
    3. Channel在NIO中是一个接口
      public interface Channel extends Closeable{}
    4. 常用的 Channel 类有:FileChannel、DatagramChannel、ServerSocketChannel 和 SocketChannel;【ServerSocketChanne 类似 ServerSocket , SocketChannel 类似 Socket】
    5. FileChannel 用于文件的数据读写,DatagramChannel 用于 UDP 的数据读写,ServerSocketChannel 和 SocketChannel 用于 TCP 的数据读写;

    二、FileChannel 类

    FileChannel 主要用来对本地文件进行 IO 操作,常见的方法有:

    // 站在Buffer角度看,read in 数据到Buffer,从Bufferwrite out Channel
    public int read(ByteBuffer dst) //从通道读取数据并放到缓冲区中
    public int write(ByteBuffer src) //把缓冲区的数据写到通道中
    public long transferFrom(ReadableByteChannel src, long position, long count) //从目标通道中复制数据到当前通道
    public long transferTo(long position, long count, WritableByteChannel target) //把数据从当前通道复制给目标通道
    
    • 1
    • 2
    • 3
    • 4
    • 5

    三、Channel 应用案例

    1. 应用实例 1 - 本地文件写数据

    实例要求:
    (1)用 ByteBuffer(缓冲) 和 FileChannel(通道), 将 “hello,你好” 写入到 file01.txt 中;
    (2)文件不存在就创建;

    import java.io.FileOutputStream;
    import java.nio.ByteBuffer;
    import java.nio.channels.FileChannel;
    
    public class NIOFileChannel01 {
        public static void main(String[] args) throws Exception{
    
            String str = "hello,你好";
            // 创建一个输出流
            FileOutputStream fileOutputStream = new FileOutputStream("D:\\GitHub\\NettyDemo\\file01.txt");
    
            // 通过 fileOutputStream 获取对应的 FileChannel
            // 这个 fileChannel 真实类型是 FileChannelImpl
            FileChannel fileChannel = fileOutputStream.getChannel();
    
            // 创建一个缓冲区 ByteBuffer
            ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
    
            // 将 str 放入 byteBuffer
            byteBuffer.put(str.getBytes());
    
            // 对byteBuffer 进行flip
            byteBuffer.flip();
    
            // 将byteBuffer 数据写到 fileChannel
            fileChannel.write(byteBuffer);
            fileOutputStream.close();
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    2. 应用实例 2 - 本地文件读数据

    (1)使用 ByteBuffer(缓冲) 和 FileChannel(通道), 将 file01.txt 中的数据读入到程序,并显示在控制台;
    (2)假定文件已经存在;

    public class NIOFileChannel02 {
        public static void main(String[] args) throws Exception {
    
            // 创建文件的输入流
            File file = new File("D:\\GitHub\\NettyDemo\\file01.txt");
            FileInputStream fileInputStream = new FileInputStream(file);
    
            // 通过fileInputStream 获取对应的FileChannel -> 实际类型  FileChannelImpl
            FileChannel fileChannel = fileInputStream.getChannel();
    
            // 创建缓冲区
            ByteBuffer byteBuffer = ByteBuffer.allocate((int) file.length());
    
            // 将通道的数据读入到Buffer
            fileChannel.read(byteBuffer);
    
            // 将byteBuffer 的字节数据 转成String
            System.out.println(new String(byteBuffer.array()));
            fileInputStream.close();
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    输出:

    hello,你好

    3. 应用实例 3 - 使用一个Buffer 完成文件读取、写入

    实例要求:
    (1)使用 FileChannel(通道) 和 方法 read 、 write,完成文件的拷贝;
    (2)拷贝一个文本文件 file01.txt , 放在项目下即可;

    在这里插入图片描述

    public class NIOFileChannel03 {
        public static void main(String[] args) throws Exception {
    
            FileInputStream fileInputStream = new FileInputStream("1.txt");
            FileChannel fileChannel01 = fileInputStream.getChannel();
    
            FileOutputStream fileOutputStream = new FileOutputStream("2.txt");
            FileChannel fileChannel02 = fileOutputStream.getChannel();
    
            ByteBuffer byteBuffer = ByteBuffer.allocate(512);
    
            // 循环读取
            while (true) {
    
                // 这里有一个重要的操作,一定不要忘了
                /*public Buffer clear() { // clear源码
    		       position = 0;
    		        limit = capacity;
    		        mark = -1;
    		        return this;
    		    }*/
                // 清空buffer
                // 如果不clear,此时position=limit,则read的返回值为0,退不出循环,还会一直重复写
                byteBuffer.clear();
                int read = fileChannel01.read(byteBuffer);
                System.out.println("read = " + read);
                // 表示读完
                if(read == -1) {
                    break;
                }
                // 将buffer 中的数据写入到 fileChannel02 -- 2.txt
                byteBuffer.flip();
                fileChannel02.write(byteBuffer);
            }
    
            // 关闭相关的流
            fileInputStream.close();
            fileOutputStream.close();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    4. 应用实例 4 - 拷贝文件transferFrom方法

    实例要求:
    (1)使用 FileChannel(通道) 和 transferFrom方法,完成文件的拷贝;
    (2)拷贝一张图片;

    public class NIOFileChannel04 {
        public static void main(String[] args)  throws Exception {
            // 创建相关流
            FileInputStream fileInputStream = new FileInputStream("D:\\GitHub\\NettyDemo\\a.png");
            FileOutputStream fileOutputStream = new FileOutputStream("D:\\GitHub\\NettyDemo\\a2.png");
    
            // 获取各个流对应的fileChannel
            FileChannel sourceChannel = fileInputStream.getChannel();
            FileChannel destChannel = fileOutputStream.getChannel();
    
            // 使用transferForm完成拷贝
            destChannel.transferFrom(sourceChannel, 0, sourceChannel.size());
            // 关闭相关通道和流
            sourceChannel.close();
            destChannel.close();
            fileInputStream.close();
            fileOutputStream.close();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
  • 相关阅读:
    数据结构————树
    ClickHouse count 查询卡在 Progress 界面一直等待
    深度学习推荐系统--协同过滤推荐算法+实现代码
    [附源码]JAVA毕业设计抗击新冠疫情专题宣传网站(系统+LW)
    Python 图_系列之基于邻接矩阵实现广度、深度优先路径搜索算法
    适用于医美行业的微信管理系统
    NVMe-MI协议解读
    React:五、React脚手架应用
    Elasticsearch 认证模拟题 - 22
    入门篇-其之六-附录一-以Java字节码的角度分析i++和++i
  • 原文地址:https://blog.csdn.net/qq_36602071/article/details/128157762