zoukankan      html  css  js  c++  java
  • 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):将多个缓冲区中的数据聚集到通道中
  • 相关阅读:
    loadrunner压测java请求
    Omnitty的使用
    软件工程之感想
    《人月神话》读后感
    my idea之NSBC分析
    电梯调度 总结稿 刘博&徐梦迪
    敏捷开发综述
    数组最大子数组和(续)之动态规划
    求二维数组最大子数组和 刘博&徐梦迪
    数组中的最大子数组的和 刘博&徐梦迪
  • 原文地址:https://www.cnblogs.com/mostro/p/11977267.html
Copyright © 2011-2022 走看看