• Java NIO 三大组件之 Channel


    Java NIO 之 Channel

    一、什么是Channel

    Channel用于源节点(例如磁盘)与目的节点的连接,它可以进行读取,写入,映射和读/写文件等操作。

    在Java NIO中负责缓冲区中数据的传输。Channel本省不存储数据,因此需要配合缓冲区进行传输。(个人理解其实就是相当于保存两通信地间的上写问和进行读写操作,相当于邮局)

    二、通道的主要实现类

    java.nio.channels.Channel接口:

    • FileChannel(本地)
    • SocketChannel(TCP)
    • ServerSocketChannel(TCP)
    • DatagramChannel(UDP)

    三、获取通道的方式

    1. Java 针对支持通道的类提供了getChannel()方法
      • FileInputStream/FileOutputStream(本地IO)
      • RandomAccessFile(本地IO)
      • Socket(网络IO)
      • ServerSocket(网络IO)
      • DatagramSocket(网络IO)
    2. 在JDK1.7中NIO.2针对各个通道提供了静态方法open()
    3. 在JDK1.7中NIO.2的Files工具类的newByteChannel()

    四、通道之间的数据传输

    • transferFrom()
    • transferTo()
    @Test
    public void test3() throws IOException {
        FileChannel inChannel = FileChannel.open(Paths.get("2.jpg"), StandardOpenOption.READ);
        FileChannel outchannel = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.WRITE, StandardOpenOption.READ, StandardOpenOption.CREATE);
    
    
        inChannel.transferTo(0,inChannel.size(),outchannel);
        //outchannel.transferFrom(inChannel, 0,inChannel.size());
        inChannel.close();
        outchannel.close();
    }
    

    其他两种两种传输方式

    1. 使用直接缓冲区完成文件的复制(内存映射文件)
    //实验证明如果传大型文件内存会出现大量占用,如果GC不对内存进行回收,无法确定OS何时把数据写入磁盘
    @Test
    public void test2() throws IOException {
        FileChannel inChannel = FileChannel.open(Paths.get("2.jpg"), StandardOpenOption.READ);
        FileChannel outchannel = FileChannel.open(Paths.get("1.jpg"), 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);
    
    }
    
    1. 利用通道完成文件的复制(非直接缓冲区)
    @Test
    public void test1(){
        String path = this.getClass().getClassLoader().getResource("1.jpg").getPath();
    
        FileInputStream fis = null;
        FileOutputStream fos = null;
    
        FileChannel fisChannel = null;
        FileChannel fosChannel = null;
        try {
             fis = new FileInputStream(path);
             fos = new FileOutputStream("src/main/resources/2.jpg");
    
            //获取通道
             fisChannel = fis.getChannel();
             fosChannel = fos.getChannel();
    
            //二、分配指定大小的缓冲区
            ByteBuffer buf = ByteBuffer.allocate(1024);
    
            //三、将通道中的数据存入缓冲区中
            while(fisChannel.read(buf) != -1){
                buf.flip(); //切换读取数据的模式
                //四、将缓冲区的数据写入通道中
                fosChannel.write(buf);
                buf.clear();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
    
            try {
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    

    分散(Scatter)与聚集(Gather)

    • 分散读取(Scattering Reads): 将通道中的数据分散到多个缓冲区中
    • 聚集写入(Gathering Writes):将多个缓冲区中的数据聚集到通道中
  • 相关阅读:
    begin lydsy 2731
    关于js中this关键字的补充
    js中this关键字测试集锦
    js文件中函数前加分号和感叹号是什么意思?
    好用的wget命令从下载添加环境变量到各参数详解
    一个解析json串并组装echarts的option的函数解析
    oschina代码仓库远程push,pull免密实操总结
    yii 核心类classes.php详解(持续更新中...)
    yii2.0归档安装方法
    配置windows 系统PHP系统环境变量
  • 原文地址:https://www.cnblogs.com/mostro/p/11977267.html
Copyright © 2020-2023  润新知