Maison Java javaDidacticiel java中io与nio复制文件性能对比

java中io与nio复制文件性能对比

Nov 22, 2016 pm 02:11 PM
java

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。然后用户进程再将数据从内核缓冲区拷贝到用户空间缓冲区。用户进程再从用户空间缓冲区中读取数据。因为用户进程是不可以直接访问硬件的。所以需要通过内核来充当中间人的作用来实现文件的读取。

整个过程如下图所示:55651933a6254.jpg

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

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

55651933a6254.jpg

下面就看下使用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(); 
    
     } 
    
 } 


Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

Video Face Swap

Video Face Swap

Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Nombre parfait en Java Nombre parfait en Java Aug 30, 2024 pm 04:28 PM

Guide du nombre parfait en Java. Nous discutons ici de la définition, comment vérifier le nombre parfait en Java ?, des exemples d'implémentation de code.

Weka en Java Weka en Java Aug 30, 2024 pm 04:28 PM

Guide de Weka en Java. Nous discutons ici de l'introduction, de la façon d'utiliser Weka Java, du type de plate-forme et des avantages avec des exemples.

Numéro de Smith en Java Numéro de Smith en Java Aug 30, 2024 pm 04:28 PM

Guide du nombre de Smith en Java. Nous discutons ici de la définition, comment vérifier le numéro Smith en Java ? exemple avec implémentation de code.

Questions d'entretien chez Java Spring Questions d'entretien chez Java Spring Aug 30, 2024 pm 04:29 PM

Dans cet article, nous avons conservé les questions d'entretien Java Spring les plus posées avec leurs réponses détaillées. Pour que vous puissiez réussir l'interview.

Break or Return of Java 8 Stream Forach? Break or Return of Java 8 Stream Forach? Feb 07, 2025 pm 12:09 PM

Java 8 présente l'API Stream, fournissant un moyen puissant et expressif de traiter les collections de données. Cependant, une question courante lors de l'utilisation du flux est: comment se casser ou revenir d'une opération FOREAK? Les boucles traditionnelles permettent une interruption ou un retour précoce, mais la méthode Foreach de Stream ne prend pas directement en charge cette méthode. Cet article expliquera les raisons et explorera des méthodes alternatives pour la mise en œuvre de terminaison prématurée dans les systèmes de traitement de flux. Lire plus approfondie: Améliorations de l'API Java Stream Comprendre le flux Forach La méthode foreach est une opération terminale qui effectue une opération sur chaque élément du flux. Son intention de conception est

Horodatage à ce jour en Java Horodatage à ce jour en Java Aug 30, 2024 pm 04:28 PM

Guide de TimeStamp to Date en Java. Ici, nous discutons également de l'introduction et de la façon de convertir l'horodatage en date en Java avec des exemples.

Programme Java pour trouver le volume de la capsule Programme Java pour trouver le volume de la capsule Feb 07, 2025 am 11:37 AM

Les capsules sont des figures géométriques tridimensionnelles, composées d'un cylindre et d'un hémisphère aux deux extrémités. Le volume de la capsule peut être calculé en ajoutant le volume du cylindre et le volume de l'hémisphère aux deux extrémités. Ce tutoriel discutera de la façon de calculer le volume d'une capsule donnée en Java en utilisant différentes méthodes. Formule de volume de capsule La formule du volume de la capsule est la suivante: Volume de capsule = volume cylindrique volume de deux hémisphères volume dans, R: Le rayon de l'hémisphère. H: La hauteur du cylindre (à l'exclusion de l'hémisphère). Exemple 1 entrer Rayon = 5 unités Hauteur = 10 unités Sortir Volume = 1570,8 unités cubes expliquer Calculer le volume à l'aide de la formule: Volume = π × r2 × h (4

Créer l'avenir : programmation Java pour les débutants absolus Créer l'avenir : programmation Java pour les débutants absolus Oct 13, 2024 pm 01:32 PM

Java est un langage de programmation populaire qui peut être appris aussi bien par les développeurs débutants que par les développeurs expérimentés. Ce didacticiel commence par les concepts de base et progresse vers des sujets avancés. Après avoir installé le kit de développement Java, vous pouvez vous entraîner à la programmation en créant un simple programme « Hello, World ! ». Une fois que vous avez compris le code, utilisez l'invite de commande pour compiler et exécuter le programme, et « Hello, World ! » s'affichera sur la console. L'apprentissage de Java commence votre parcours de programmation et, à mesure que votre maîtrise s'approfondit, vous pouvez créer des applications plus complexes.

See all articles