利用NIO实现文件拷贝

利用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不需要,点了奶茶,奶茶在做,我可以去再吃个绝味鸭脖,吃完回来再拿

参考上一篇

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值