利用NIO实现文件拷贝
项目里面可能会有 把某文件从磁盘的这个地方拷贝到磁盘的另外一个地方
实现的方式有很多种,IO,apache的工具类,JDK自带的文件拷贝等等等
为什么我要选择NIO呢?请参照上一篇文章!
我们先用IO也就是原始的方法来实现,也就是所谓的BIO 同步阻塞式IO(不秒懂请参照上一篇文章 )
/**
* Created by IntelliJ IDEA.
* User: kt
* Date: 2021/3/30 15:36
*
* @author kt
* 利用io实现文件拷贝
*/
public class IOCopy {
//定义缓冲区的大小 1M
private static final int BUFFER_SIZE = 1024;
@SneakyThrows
public static void copyFile(String source, String target) {
long startTime = System.currentTimeMillis();
//定义文件输入出入流
FileInputStream in = new FileInputStream(new File(source));
FileOutputStream out = new FileOutputStream(new File(target));
byte[] buffer = new byte[BUFFER_SIZE];
int len;
while ((len = in.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
System.out.println(String.format("IO file copy cost %d msc", System.currentTimeMillis() - startTime));
}
public static void main(String[] args) {
String source = "D:\\Desktop.JPEG";
String target = "E:\\Desktop.JPEG";
copyFile(source, target);
//IO file copy cost 31 msc
}
}
NIO实现的方式又有两种了,一种是通过管道,NIO三大核心部分之一
/**
* Created by IntelliJ IDEA.
* User: kt
* Date: 2021/3/30 15:54
*
* @author 匡涛
* nio文件拷贝 通过管道
*/
public class NIOCopy {
@SneakyThrows
public static void copyFile(String source, String target) {
long startTime = System.currentTimeMillis();
//得到管道
FileChannel input = new FileInputStream(new File(source)).getChannel();
FileChannel output = new FileOutputStream(new File(target)).getChannel();
//通过输出管道从输入管道里提取文件
output.transferFrom(input, 0, input.size());
System.out.println(String.format("NIO file copy cost %d msc", System.currentTimeMillis() - startTime));
}
public static void main(String[] args) {
String source = "D:\\Desktop.JPEG";
String target = "E:\\Desktop.JPEG";
copyFile(source, target);
//NIO file copy cost 9 msc
}
重点来了:文件内存映射
把内核空间地址与用户空间的虚拟地址映射到同一个物理地址,DMA 硬件可以填充对内核与用户空间进程同时可见的缓冲区了。用户进程直接从内存中读取文件内容,应用只需要和内存打交道,不需要进行缓冲区来回拷贝,大大提高了IO拷贝的效率。加载内存映射文件所使用的内存在Java堆区之外
硬件的东西我也不是很懂,我们就关注怎么存取的就行!
/**
* Created by IntelliJ IDEA.
* User: kt
* Date: 2021/3/30 16:11
*
* @author 匡涛
* nio实现文件拷贝 文件内存映射
*/
public class NIOCopyFile2 {
@SneakyThrows
public static void copyFile(String source, String target) {
long start = System.currentTimeMillis();
FileInputStream fis = new FileInputStream(new File(source));
FileOutputStream fos = new FileOutputStream(new File(target));
FileChannel sourceChannel = fis.getChannel();
FileChannel targetChannel = fos.getChannel();
MappedByteBuffer mappedByteBuffer = sourceChannel.map(FileChannel.MapMode.READ_ONLY, 0, sourceChannel.size());
targetChannel.write(mappedByteBuffer);
System.out.println(String.format("NIO memory reflect file copy cost %d msc", System.currentTimeMillis() - start));
File targetFile = new File(target);
targetFile.delete();
}
public static void main(String[] args) {
String source = "D:\\Desktop.JPEG";
String target = "E:\\Desktop.JPEG";
copyFile(source, target);
//NIO memory reflect file copy cost 6 msc
}
}
重点不在效率上,因为很多因素可以影响
BIO和NIO最主要的区别是在 线程开销,非阻塞上面 ,而IO的流是可以阻塞的,就打个比方来说,我买一杯奶茶BIO可能需要一直等到拿到奶茶为止才能做其他事情,而NIO不需要,点了奶茶,奶茶在做,我可以去再吃个绝味鸭脖,吃完回来再拿
参考上一篇