NIO 拷贝文件真的比 IO 效率高 ?

简介:

本文是基于单线程的NIO和IO拷贝文件比较, 并未对并发做测试, 请勿过度纠结场景!

今天发现项目中有个FileUtils.copy的工具方法, 打开后发现是基于io的, 我给改成了基于NIO的, 突然疑虑NIO拷贝文件真的如其他人说的那样比IO效率高很多么?

以下是我的工具方法:

/**
     * 
     * <p>通过NIO进行文件拷贝</p>
     * @param fromFile    被拷贝的文件
     * @param toFile    拷贝后的文件
     * @throws IOException 
     */
    public static void copy(String fromFile, String toFile) throws IOException {
        FileInputStream inputStream = new FileInputStream(fromFile);
        FileChannel fromChannel = inputStream.getChannel();
        
        FileOutputStream outputStream = new FileOutputStream(toFile);
        FileChannel toChannel   = outputStream.getChannel();
        
        toChannel.transferFrom(fromChannel, 0, fromChannel.size());
//        fromChannel.transferTo(0, fromChannel.size(), toChannel);
        
        toChannel.force(true);
        inputStream.close();
        fromChannel.close();
        outputStream.close();
        toChannel.close();
    }
    
    /**
     * 
     * <p>使用IO拷贝文件</p>
     * @param fromFile        被拷贝的文件
     * @param toFile        拷贝后的文件
     * @throws IOException
     */
    public static void copyByIO(String fromFile, String toFile) throws IOException {
        File inputFile = new File(fromFile);
        File outputFile = new File(toFile);
        FileInputStream inputStream = new FileInputStream(inputFile);
        FileOutputStream outputStream = new FileOutputStream(outputFile);
        byte[] bytes = new byte[1024];
        int c;
        while ((c = inputStream.read(bytes)) != -1)
            outputStream.write(bytes, 0, c);
        inputStream.close();
        outputStream.close();
    }

以下是测试方法:

@Test
    //8.72M文本文件-->拷贝100次: 8781        1000次:101564
    //4.65G压缩包同文件夹拷贝1次:136160        跨盘拷贝1次:147363    
    public void testCopyNIO() {
        String from = "d:/test/test.zip";
        Long start = System.currentTimeMillis();
        try {
            for(int i=0;i<1;i++) {
                String to   = "e:/test/test"+i+".zip";
                FileUtils.copy(from, to);
            }
            
        } catch (IOException e) {
            e.printStackTrace();
        }
        Long end = System.currentTimeMillis();
        System.out.println(end-start);
    }

    @Test
    //8.72M文本文件-->拷贝100次: 7719        1000次:109051
    //4.65G压缩包同文件夹拷贝1次:103261        跨盘拷贝1次:76799
    public void testCopyIO() {
        String from = "d:/test/test.zip";
        Long start = System.currentTimeMillis();
        try {
            for(int i=0;i<1;i++) {
                String to   = "e:/test/test"+i+".zip";
                FileUtils.copyByIO(from, to);
            }
            
        } catch (Exception e) {
            e.printStackTrace();
        }
        Long end = System.currentTimeMillis();
        System.out.println(end-start);
    }

第一次我找了个sysbase通过bcp命令导出的数据文件, 大小为8718KB, 使用以上两个测试方法, 分别拷贝了100次, 发现NIO执行时间为8781毫秒,IO执行时间为7719毫秒, NIO输了。

第二次我将拷贝次数改成了1000, 发现NIO执行时间为101564毫秒,IO执行时间为109051毫秒, NIO赢了, 但也仅仅赢了不到8秒。

第三次我将数据文件复制打包再复制再打包最后做出一个4,650,673KB大小的压缩包, 由于磁盘空间问题, 这次我只执行了1次, 发现NIO执行时间为136160毫秒,IO执行时间为103261毫秒, NIO输了33秒。

我又怀疑同一个文件夹下面拷贝可能没有突出NIO的优势,于是我又做了第四次测试, 换了个磁盘, 结果发现NIO执行时间为147363毫秒,IO执行时间为76799毫秒, NIO输了更惨, 耗费时间足足是IO的两倍。

可见NIO虽然在很多方面比IO强,但是这也并不是绝对的。

以上只是针对NIO和普通IO的简单测试, 并没有深究文件拷贝, 有兴趣的兄弟可以去研究下通过BufferedInputStream和RandomAccessFile来进行文件拷贝。其中RandomAccessFile效率应该和FileInputStream差不多, BufferedInputStream肯定比其他的要高效很多。

相关文章
|
1月前
|
Java 测试技术 Maven
Maven clean 提示文件 java.io.IOException
在使用Maven进行项目打包时,遇到了`Failed to delete`错误,尝试手动删除目标文件也失败,提示`java.io.IOException`。经过分析,发现问题是由于`sys-info.log`文件被其他进程占用。解决方法是关闭IDEA和相关Java进程,清理隐藏的Java进程后重新尝试Maven clean操作。最终问题得以解决。总结:遇到此类问题时,可以通过任务管理器清理相关进程或重启电脑来解决。
|
5月前
|
Java 大数据
解析Java中的NIO与传统IO的区别与应用
解析Java中的NIO与传统IO的区别与应用
|
1月前
|
消息中间件 缓存 Java
java nio,netty,kafka 中经常提到“零拷贝”到底是什么?
零拷贝技术 Zero-Copy 是指计算机执行操作时,可以直接从源(如文件或网络套接字)将数据传输到目标缓冲区, 而不需要 CPU 先将数据从某处内存复制到另一个特定区域,从而减少上下文切换以及 CPU 的拷贝时间。
java nio,netty,kafka 中经常提到“零拷贝”到底是什么?
|
2月前
|
搜索推荐 索引
【文件IO】实现:查找文件并删除、文件复制、递归遍历目录查找文件
【文件IO】实现:查找文件并删除、文件复制、递归遍历目录查找文件
41 2
|
2月前
|
编解码 Java 程序员
【文件IO】文件内容操作
【文件IO】文件内容操作
58 2
|
2月前
|
存储 Java API
【文件IO】文件系统操作
【文件IO】文件系统操作
51 1
|
3月前
|
Java 大数据 API
Java 流(Stream)、文件(File)和IO的区别
Java中的流(Stream)、文件(File)和输入/输出(I/O)是处理数据的关键概念。`File`类用于基本文件操作,如创建、删除和检查文件;流则提供了数据读写的抽象机制,适用于文件、内存和网络等多种数据源;I/O涵盖更广泛的输入输出操作,包括文件I/O、网络通信等,并支持异常处理和缓冲等功能。实际开发中,这三者常结合使用,以实现高效的数据处理。例如,`File`用于管理文件路径,`Stream`用于读写数据,I/O则处理复杂的输入输出需求。
242 12
|
2月前
|
存储 Java 程序员
【Java】文件IO
【Java】文件IO
39 0
|
4月前
|
网络协议 Oracle Java
【IO面试题 三】、说说NIO的实现原理
Java NIO的实现原理基于Channel、Buffer和Selector,支持从Channel读取数据到Buffer以及从Buffer写入数据到Channel,并通过Selector实现单线程多Channel的事件驱动IO操作。
【IO面试题 三】、说说NIO的实现原理
|
3月前
|
Linux C语言
C语言 文件IO (系统调用)
本文介绍了Linux系统调用中的文件I/O操作,包括文件描述符、`open`、`read`、`write`、`lseek`、`close`、`dup`、`dup2`等函数,以及如何获取文件属性信息(`stat`)、用户信息(`getpwuid`)和组信息(`getgrgid`)。此外还介绍了目录操作函数如`opendir`、`readdir`、`rewinddir`和`closedir`,并提供了相关示例代码。系统调用直接与内核交互,没有缓冲机制,效率相对较低,但实时性更高。