Android开发Android开发经验谈Android开发

Java文件拷贝方式?哪一种最高效?

2018-08-02  本文已影响17人  遛狗的程序员

问题:

Java有几种文件拷贝方式?哪一种最高效?

知识点补充:

  1. 拷贝实现机制分析
image

从上图可知,当我们使用输入输出流进行读写时,实际上是进行了多次上下文切换,比如应用读取数据时,先在内核态讲数据从磁盘读取到内核缓存,再切换到用户态将数据从内核缓存读取到用户缓存。写入操作类似。

image

而基于NIO transferTo的实现方式,在Linux和Unix上,会使用零拷贝技术,数据传输并不需要用户态参与,省去了上下午切换的开销和不必要的内存拷贝,进而可提高应用拷贝性能。

注意:transferTo不仅仅是可以用在文件拷贝中,与其类似的,例如读取磁盘文件,然后进行Socket发送,同样可以享受这种机制带来的性能和扩展性提高。突然想到日志开发中使用到的mmap和其类似,又不一样,有兴趣可以参考:认真分析mmap:是什么 为什么 怎么用

回答问题:

Java有多种比较典型的文件拷贝实现方式,比如:
利用java.io类库,直接为源文件构建一个FileInputStream读取,然后再为目标文件构建一个FileOutputStream,完成写入工作。

public static void copyFileByStream(File source,File dest) throws IOException{
        try(InputStream inputStream = new FileInputStream(source);
            OutputStream outputStream = new FileOutputStream(dest)){
            byte[] buffer = new byte[1024];
            int length;
            while ((length = inputStream.read(buffer))>0){
                outputStream.write(buffer,0,length);
            }
        }
    }

或者,利用java.nio类库提供的transferTo或者transferFrom方法实现。

/**
     * 复制文件,使用nio以提高性能
     *
     * @param src  - 源文件
     * @param dest - 目标文件
     */
    public static void copyFile(File src, File dest) {
        FileInputStream fis = null;
        FileOutputStream fos = null;
        FileChannel in = null;
        FileChannel out = null;
        try {
            fis = new FileInputStream(src);
            fos = new FileOutputStream(dest);
            in = fis.getChannel(); // 得到对应的文件通道
            out = fos.getChannel(); // 得到对应的文件通道
            in.transferTo(0, in.size(), out); // 连接两个通道,并且从in通道读取,然后写入out通道
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            IoUtils.closeQuietly(fis);
            IoUtils.closeQuietly(in);
            IoUtils.closeQuietly(fos);
            IoUtils.closeQuietly(out);
        }
    }

当然,Java标准类库本身已经提供了几种File.copy方法的实现(我在Android目前还没用到),或者使用使用Apache Commons IO提供的提供了一个FileUtils.copyFile(File from, File to)方法用于文件复制,如果项目里使用到了这个类库,使用这个方法是个不错的选择。它的内部也是使用Java NIO的FileChannel实现的(我在Android目前还没用到)。有兴趣可以参考:文件复制的 4 种实现方式及性能对比

对于Copy的效率,这个其实与操作系统和配置等情况有关。总体来说,NIO transferTo/From的方式可能更快,因为它更能利用现在操作系统底层机制,避免不必要的拷贝和上下文切换

参考:

声明:此为原创,转载请联系作者


作者:微信公众号添加公众号-遛狗的程序员 ,或者可以扫描以下二维码关注相关技术文章。

qrcode_for_gh_1ba0785324d6_430.jpg

当然喜爱技术,乐于分享的你也可以可以添加作者微信号:

WXCD.jpeg
上一篇 下一篇

猜你喜欢

热点阅读