2019独角兽企业重金招聘Python工程师标准>>>

1.  在JAVA传统的IO系统中,读取磁盘文件数据的过程如下:

以FileInputStream类为例,该类有一个read(byte b[])方法,byte b[]是我们要存储读取到用户空间的缓冲区。参看read(byte b[])方法的源码,可知,它会在内部再调用readBytes(b, 0, b.length)方法,而且readBytes(b, 0, b.length)方法是一个native方法(即本地方法),最终通过这个本地方法来发起一次系统调用,即调用系统内核的read()方法,内核从磁盘读取数据到内核缓冲区,这个过程由磁盘控制器通过DMA操作将数据从磁盘读取内核缓冲区,此过程不依赖于CPU。然后用户进程再将数据从内核缓冲区拷贝到用户空间缓冲区。用户进程再从用户空间缓冲区中读取数据。因为用户进程是不可以直接访问硬件的。所以需要通过内核来充当中间人的作用来实现文件的读取。整个过程如下图所示:

2.  自从JAVA 1.4以后,JAVA在NIO在引入了文件通道的概念,和传统IO最大的区别是:传统IO是基于Byte(字节)和Stream(流)的,而NIO是基于Buffer(缓冲)、Channel(通道)在API中有提供了一个FileChannel类和Selector(选择器)的,该类与传统的IO流进行关联。可以由FileInputStream或FileOutputStream获取该文件通道,我们可以通过通道对文件进行读写操作。

3.JAVA NIO中还引入了文件内存映射的概念:现代操作系统大都支持虚拟内存映射,这样,我们可以把内核空间地址与用户空间的虚拟地址映射到同一个物理地址,这样,DMA 硬件(只能访问物理内存地址)就可以填充对内核与用户空间进程同时可见的缓冲区了。如下图所示:

下面就看下使用IO,BufferedIO和NIO分别实现的文件复制耗时比较:11兆音频文件

传统IO方法实现文件拷贝耗时:21ms
利用NIO文件通道方法实现文件拷贝耗时:16ms
利用NIO文件内存映射及文件通道实现文件拷贝耗时:7ms
利用FileUtils文件拷贝工具类耗时:53ms

package com.maystar.utils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

import org.apache.commons.io.FileUtils;

public class FileCopyTest { 
     
      public  static  void main(String[] args) throws Exception { 
     
         String sourcePath = "F:\\glzmv.mp3"; 
     
         String destPath1 = "F:\\glzmvCopy1.mp3"; 
     
         String destPath2 = "F:\\glzmvCopy2.mp3"; 
     
         String destPath3 = "F:\\glzmvCopy3.mp3"; 
         
         String destPath4 = "F:\\glzmvCopy4.mp3"; 
         long t1 = System.currentTimeMillis(); 
    
         traditionalCopy(sourcePath,destPath1); 
     
         long t2 = System.currentTimeMillis(); 
     
         System.out.println("传统IO方法实现文件拷贝耗时:" + (t2-t1) + "ms"); 
     
         nioCopy(sourcePath,destPath2); 
     
         long t3 = System.currentTimeMillis(); 
     
         System.out.println("利用NIO文件通道方法实现文件拷贝耗时:" + (t3-t2) + "ms"); 
         nioCopy2(sourcePath,destPath3); 
     
         long t4 = System.currentTimeMillis(); 
     
         System.out.println("利用NIO文件内存映射及文件通道实现文件拷贝耗时:" + (t4-t3) + "ms"); 
         
         nioCopy3(sourcePath,destPath4); 
         long t5 = System.currentTimeMillis(); 
         System.out.println("利用FileUtils文件拷贝耗时:" + (t5-t4) + "ms"); 
      } 
      private  static  void nioCopy3(String sourcePath, String destPath) throws Exception { 
             
          File source = new File(sourcePath); 
      
          File dest = new File(destPath); 
      
      
         FileUtils.copyFile(source, dest);//查看源码commons-io-2.4也使用的是nio操作,实现类似nioCopy操作,但是为什么效率比nioCopy要低,原因是在FileUtils.copyFile执行doCopyFile完成调用IOUtils工具类关闭流操作,根据不同类型的流调用对应的构造方法。
      
       } 
      
      private  static  void nioCopy2(String sourcePath, String destPath) throws Exception { 
     
         File source = new File(sourcePath); 
     
         File dest = new File(destPath); 
     
         if(!dest.exists()) { 
     
             dest.createNewFile(); 
         } 
         FileInputStream fis = new FileInputStream(source); 
     
         FileOutputStream fos = new FileOutputStream(dest); 
     
         FileChannel sourceCh = fis.getChannel(); 
     
         FileChannel destCh = fos.getChannel(); 
     
         MappedByteBuffer mbb = sourceCh.map(FileChannel.MapMode.READ_ONLY, 0, sourceCh.size()); 
     
         destCh.write(mbb); 
     
         sourceCh.close(); 
     
         destCh.close(); 
     
      } 
     
      private  static  void traditionalCopy(String sourcePath, String destPath) throws Exception{ 
     
         File source = new File(sourcePath); 
     
         File dest = new File(destPath); 
     
         if(!dest.exists()) { 
    
            dest.createNewFile(); 
    
        } 
    
        FileInputStream fis = new FileInputStream(source); 
    
        FileOutputStream fos = new FileOutputStream(dest); 
    
        byte [] buf = new byte [fis.available()]; 
    
        int len = 0; 
    
        while((len = fis.read(buf)) != -1) { 
    
            fos.write(buf, 0, len); 
    
        } 
    
        fis.close(); 
    
        fos.close(); 
    
     } 
    
     private  static  void nioCopy(String sourcePath, String destPath) throws Exception{ 
    
        File source = new File(sourcePath); 
    
        File dest = new File(destPath); 
    
        if(!dest.exists()) { 
    
            dest.createNewFile(); 
    
        } 
    
        FileInputStream fis = new FileInputStream(source); 
    
        FileOutputStream fos = new FileOutputStream(dest); 
    
        FileChannel sourceCh = fis.getChannel(); 
       
    
        FileChannel destCh = fos.getChannel(); 
        destCh.transferFrom(sourceCh, 0, sourceCh.size()); 
    
        sourceCh.close(); 
    
        destCh.close(); 
    
     } 
    
 }

转载于:https://my.oschina.net/u/1054538/blog/770067

java中io与nio复制文件性能对比相关推荐

  1. Java中IO和NIO的本质和区别

    文章目录 简介 IO的本质 DMA和虚拟地址空间 IO的分类 IO和NIO的区别 总结 简介 终于要写到java中最最让人激动的部分了IO和NIO.IO的全称是input output,是java程序 ...

  2. Java中IO(一、文件流)

    文件流 FileInputStream从文件系统中的文件获取输入字节.哪些文件可用取决于主机环境. FileInputStream用于读取原始字节流,如图像数据.要读取字符流,请考虑使用FileRea ...

  3. io读取一个文件再写入socket技术_JAVA中IO与NIO面试题

    BIO.NIO有什么区别? BIO:Block IO 同步阻塞式 IO,就是我们平常使用的传统 IO,它的特点是模式简单使用方便,并发处理能力低. NIO:New IO 同步非阻塞 IO,是传统 IO ...

  4. java 中 IO 的流的种类及BIO、NIO、AIO 有什么区别?

    文章目录 java 中 IO 流分为几种? BIO.NIO.AIO 有什么区别? java 中 IO 流分为几种? (1)按流划分,可以分为输入流和输出流: (2)按单位划分,可以分为字节流和字符流: ...

  5. 在Java中使用final关键字可以提高性能吗?

    本文翻译自:Does use of final keyword in Java improve the performance? In Java we see lots of places where ...

  6. Java之IO,BIO,NIO,AIO

    2019独角兽企业重金招聘Python工程师标准>>> 参考文献一 IO基础知识回顾 java的核心库java.io提供了全面的IO接口.包括:文件读写.标准设备输出等.Java中I ...

  7. Java之IO,BIO,NIO,AIO知多少?

    开心一笑 [一女人:"我真不放心丈夫,他准备到湖中心水最深的地方把猫扔掉."邻居:"那有什么不放心的?"女人:"猫已回家一钟头了!"] 提出 ...

  8. Linux网络IO模型及JAVA中IO模型

    文章目录 1.概述 2.Linux网络IO模型 2.1.阻塞IO模型 2.2.非阻塞IO模型 2.3.IO复用模型 2.3.1.select 2.3.2.poll 2.3.3.epoll 2.4.信号 ...

  9. Java中IO流体系

    转载: https://mp.weixin.qq.com/s?__biz=MzA5NzgzODI5NA==&mid=2454030958&idx=1&sn=df27aadb92 ...

最新文章

  1. win合适做服务器的系统,win系统做云服务器
  2. 这款AI语音模型让派大星承认自己是钢铁侠,造假小扎对口型,火到挤爆服务器|在线可玩...
  3. GitHub 上值得关注的 iOS 开源项目
  4. [深度学习] 一篇文章理解 word2vec
  5. kafka消费者接收分区测试
  6. 通过C#中的在线文件自动更新应用程序
  7. oracle 12c dbca 无法发现 asm diskgroup
  8. spring - ioc和aop
  9. ACL2021 Findings | 挖掘label的语义来增强few-shot问题
  10. vmware+player+12+linux,Vmware player 12
  11. 您的 App 包含 NSUserTrackingUsageDescription,这表示您将会请求追踪用户。要在
  12. solidity之view和pure函数的用法总结
  13. linux编译一直失败,linux编译安装时常见错误解决办法
  14. ixed php,「」解决PHP script * is protected by SourceGuardian
  15. Oracle--“ORA-28007: the password cannot be reused”解决
  16. 日本金融监管机构将推出新的ICO法规
  17. 树莓派空气质量检测之——GP2Y1010AU0F粉尘传感器模块的使用记录
  18. 【深度神经网络】五、GoogLeNet网络详解
  19. 人体动作捕捉格式BVH及其与三维坐标的转换
  20. PSP火影忍者之究极冲击 游戏ISO文件和完美通关存档

热门文章

  1. LInux线程——多线程与fork之间的问题
  2. 孤儿进程和僵死进程处理方法
  3. c++内存管理-内存顺序
  4. 【常见Web应用安全问题】
  5. list agg cause ORA-06502 PL/SQL: numeric or value error
  6. 通过hibernate去调用存储过程
  7. Java数据结构——2-3树
  8. 工业4.0的小小思考
  9. goole机器学习视频链接【学习笔记】
  10. idea spring helloworld