java中io与nio复制文件性能对比
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();
}
}

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas



Panduan Nombor Sempurna di Jawa. Di sini kita membincangkan Definisi, Bagaimana untuk menyemak nombor Perfect dalam Java?, contoh dengan pelaksanaan kod.

Panduan untuk Weka di Jawa. Di sini kita membincangkan Pengenalan, cara menggunakan weka java, jenis platform, dan kelebihan dengan contoh.

Panduan untuk Nombor Smith di Jawa. Di sini kita membincangkan Definisi, Bagaimana untuk menyemak nombor smith di Jawa? contoh dengan pelaksanaan kod.

Dalam artikel ini, kami telah menyimpan Soalan Temuduga Spring Java yang paling banyak ditanya dengan jawapan terperinci mereka. Supaya anda boleh memecahkan temuduga.

Java 8 memperkenalkan API Stream, menyediakan cara yang kuat dan ekspresif untuk memproses koleksi data. Walau bagaimanapun, soalan biasa apabila menggunakan aliran adalah: bagaimana untuk memecahkan atau kembali dari operasi foreach? Gelung tradisional membolehkan gangguan awal atau pulangan, tetapi kaedah Foreach Stream tidak menyokong secara langsung kaedah ini. Artikel ini akan menerangkan sebab -sebab dan meneroka kaedah alternatif untuk melaksanakan penamatan pramatang dalam sistem pemprosesan aliran. Bacaan Lanjut: Penambahbaikan API Java Stream Memahami aliran aliran Kaedah Foreach adalah operasi terminal yang melakukan satu operasi pada setiap elemen dalam aliran. Niat reka bentuknya adalah

Panduan untuk TimeStamp to Date di Java. Di sini kita juga membincangkan pengenalan dan cara menukar cap waktu kepada tarikh dalam java bersama-sama dengan contoh.

Kapsul adalah angka geometri tiga dimensi, terdiri daripada silinder dan hemisfera di kedua-dua hujungnya. Jumlah kapsul boleh dikira dengan menambahkan isipadu silinder dan jumlah hemisfera di kedua -dua hujungnya. Tutorial ini akan membincangkan cara mengira jumlah kapsul yang diberikan dalam Java menggunakan kaedah yang berbeza. Formula volum kapsul Formula untuk jumlah kapsul adalah seperti berikut: Kelantangan kapsul = isipadu isipadu silinder Dua jumlah hemisfera dalam, R: Radius hemisfera. H: Ketinggian silinder (tidak termasuk hemisfera). Contoh 1 masukkan Jejari = 5 unit Ketinggian = 10 unit Output Jilid = 1570.8 Unit padu menjelaskan Kirakan kelantangan menggunakan formula: Kelantangan = π × r2 × h (4

Spring Boot memudahkan penciptaan aplikasi Java yang mantap, berskala, dan siap pengeluaran, merevolusi pembangunan Java. Pendekatan "Konvensyen Lebih Konfigurasi", yang wujud pada ekosistem musim bunga, meminimumkan persediaan manual, Allo
