Java IO和Java NIO在文件拷贝上的性能差异分析
来源:互联网 发布:淘宝卖什么最赚钱 编辑:程序博客网 时间:2024/05/21 05:57
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在引入了文件通道的概念,在API中有提供了一个
FileChannel类。该类与传统的IO流进行关联。可以由FileInputStream或FileOutputStream获取该文件通道,我们可以通过通道对文件进行读写操作。
3.JAVA NIO中还引入了文件内存映射的概念:现代操作系统大都支持虚拟内存映射,这样,我们可以把内核空间地址与用户空间的虚拟地址映射到同一个物理地址,这样,DMA 硬件(只能访问物理内存地址)就可以填充对内核与用户空间进程同时可见的缓冲区了。如下图所示:
这样做的好处是,我们在读取磁盘文件时,再也不用通过内核缓冲区到用户进程缓冲区的来回拷贝操作了。操作系统会通过一些页面调度算法来将磁盘文件载入对分页区进行高速缓存的物理内存。我们就可以通过映射后物理内存来读取磁盘文件了。
3. 下面我们通过三种不同方式文件拷贝的案例来验证文件通道及文件内存映射在IO
系统中的作用。测试环境为windows 32位系统和JDK1.6。代码中使用的测试文件movie.avi为一个123MB的视频文件。代码如下:
package
cn.com.hbust.nio.file;
import
java.io.File;
import
java.io.FileInputStream;
import
java.io.FileOutputStream;
import
java.nio.MappedByteBuffer;
import
java.nio.channels.FileChannel;
public
class
FileCopyTest {
public
static
void
main(String[] args)
throws
Exception {
String sourcePath =
"F:\\mywork\\javademo\\dir1\\movie.avi"
;
String destPath1 =
"F:\\mywork\\javademo\\dir2\\movie1.avi"
;
String destPath2 =
"F:\\mywork\\javademo\\dir2\\movie2.avi"
;
String destPath3 =
"F:\\mywork\\javademo\\dir2\\movie3.avi"
;
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"
);
}
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 = newbyte [
512
];
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();
}
}
每执行完一次拷贝之后,将F:\mywork\javademo\dir2\目录中的内容删除掉,重复执行8次。观察测试结果如下:时间单位为ms(毫秒)
由上表可知,传统IO方式平均拷贝完成时间约为1968ms,NIO文件通道方式平均拷贝完成时间约为1672ms,文件内存映射及文件通道方式平均拷贝完成时间约为1418ms。
- Java IO和Java NIO在文件拷贝上的性能差异分析
- Java IO和Java NIO在文件拷贝上的性能差异分析
- Java IO和Java NIO在文件拷贝上的性能差异分析
- java对比IO和NIO的文件读写性能测试
- Java IO与NIO实现文件拷贝
- java IO和NIO性能比较
- Java Io 之拷贝文件性能比较
- NIO和阻塞io的读写文件效率差异
- Java常用面试题16 用IO和NIO两种方式实现文件拷贝
- JAVA中IO和NIO的详解分析,FileChannel
- Java中的NIO和IO的对比分析
- Java中的NIO和IO的对比分析
- java文件io、nio
- JAVA IO和NIO复制文件
- java io和nio
- java IO和NIO
- Java IO和NIO
- Java NIO和IO
- html--1-test
- maven问题记录
- Android 4.0源码目录结构
- git 提交ignore files
- ie7,8下__flash__addCallback报错原因及解决方案
- Java IO和Java NIO在文件拷贝上的性能差异分析
- 关于android不同系统样式的思考
- Java IO流学习总结(一)
- 第三方QQ账号登录的实现
- 如何部署SSL服务器证书更安全
- 高效搭建Storm完全分布式集群
- 2名"占中"发起人宣布返校 称不拖学生后腿
- PhoneGap API介绍:Device
- ucgui界面设计示例2