【问题标题】:Move / Copy File Operations in JavaJava中的移动/复制文件操作
【发布时间】:2010-09-22 23:14:19
【问题描述】:

是否有标准的 Java 库来处理常见的文件操作,例如移动/复制文件/文件夹?

【问题讨论】:

    标签: java file copy move


    【解决方案1】:

    以下是使用java.nio 操作的方法:

    public static void copyFile(File sourceFile, File destFile) throws IOException {
        if(!destFile.exists()) {
            destFile.createNewFile();
        }
    
        FileChannel source = null;
        FileChannel destination = null;
        try {
            source = new FileInputStream(sourceFile).getChannel();
            destination = new FileOutputStream(destFile).getChannel();
    
            // previous code: destination.transferFrom(source, 0, source.size());
            // to avoid infinite loops, should be:
            long count = 0;
            long size = source.size();              
            while((count += destination.transferFrom(source, count, size-count))<size);
        }
        finally {
            if(source != null) {
                source.close();
            }
            if(destination != null) {
                destination.close();
            }
        }
    }
    

    【讨论】:

    • 如果文件存在,内容会被追加还是覆盖?
    • @Rigo 这只会移动文件,我无法移动目录
    • 值得注意的是,Java 7 有更简单的copy/move methods
    • File.renameTo 不如Files.move 有什么原因?
    • @Erik Allik:如果操作失败,Files.move 会告诉你为什么,而不是简单地返回falseFiles.move 可以处理不是简单重命名的移动,即需要复制和删除。
    【解决方案2】:

    目前还没有,但New NIO (JSR 203) 将支持这些常见操作。

    与此同时,有几点需要牢记。

    File.renameTo 通常只在同一个文件系统卷上工作。我认为这相当于“mv”命令。如果可以,请使用它,但对于一般的复制和移动支持,您需要有一个后备。

    当重命名不起作用时,您将需要实际复制文件(如果是“移动”操作,则使用 File.delete 删除原始文件)。要以最高效率执行此操作,请使用 FileChannel.transferToFileChannel.transferFrom 方法。该实现是特定于平台的,但一般来说,当从一个文件复制到另一个文件时,实现会避免在内核空间和用户空间之间来回传输数据,从而大大提高效率。

    【讨论】:

      【解决方案3】:

      查看: http://commons.apache.org/io/

      它有副本,如前所述,JDK 已经移动。

      不要实现自己的复制方法。有这么多漂浮在那里......

      【讨论】:

      • Commons IO 在可以复制的文件大小方面存在限制。对于通用解决方案,预计会有更强大的实现。
      • 实现自己的复制方法是微不足道的,这意味着您不会依赖于整个库。 实现你自己的
      • 复制方法绝非易事。您可以轻松地制作一个使用 Streams 无法执行的正确操作,并使用 NIO 轻松制作一个快速但不正确的操作。当有高质量的库时,永远不要实现自己的实用程序。
      • 复制方法非平凡的,Apache Commons 无法处理一个常见的用例:信息对于主内存来说太大了。用于管理大容量存储的库应该限制其内存消耗,而 Apache Commons move 方法则缺乏这一点。
      • @Pyrolistical Never implement your own utilities when there are quality libraries out there. Uhh suure,如果您永远不必担心许可问题。
      【解决方案4】:

      以前的答案似乎已经过时了。

      Java 的 File.renameTo() 可能是 API 7 最简单的解决方案,而且似乎运行良好。 小心它不会抛出异常,而是返回真/假!!!

      请注意,它在以前的版本中似乎存在问题(与NIO 相同)。

      如果您需要使用以前的版本,请查看here

      以下是 API7 的示例:

      File f1= new File("C:\\Users\\.....\\foo");
      File f2= new File("C:\\Users\\......\\foo.old");
      System.err.println("Result of move:"+f1.renameTo(f2));
      

      或者:

      System.err.println("Move:" +f1.toURI() +"--->>>>"+f2.toURI());
      Path b1=Files.move(f1.toPath(),  f2.toPath(), StandardCopyOption.ATOMIC_MOVE ,StandardCopyOption.REPLACE_EXISTING ););
      System.err.println("Move: RETURNS:"+b1);
      

      【讨论】:

      • 如果您收到“该进程无法访问该文件,因为它正被另一个进程使用。“该进程无法访问该文件,因为它正被另一个进程使用。”第二部分的异常代码,记得在移动它之前关闭文件.....
      • 还有其他意外情况会失败,例如在 linux 上,如果在 /mnt/a /mnt/b 下挂载了两个不同的文件系统,则不能将文件 /mnt/a/file1 重命名为 /mnt/b/file2,因为它实际上是一个移动操作,File.renameTo 会在这种情况下失败。
      • 这是最好的解决方案。如果您担心重命名操作失败,只需使用 Files.move()。
      【解决方案5】:
      【解决方案6】:

      尝试使用org.apache.commons.io.FileUtils(通用文件操作实用程序)。通过以下方式提供设施:

      (1) FileUtils.moveDirectory(File srcDir, File destDir) => 移动一个 目录。

      (2) FileUtils.moveDirectoryToDirectory(File src, File destDir, boolean createDestDir) => 将一个目录移动到另一个目录。

      (3) FileUtils.moveFile(File srcFile, File destFile) => 移动文件。

      (4) FileUtils.moveFileToDirectory(File srcFile, File destDir, boolean createDestDir) => 将文件移动到目录。

      (5) FileUtils.moveToDirectory(File src, File destDir, boolean createDestDir) => 将文件或目录移动到目标 目录。

      简单、轻松、快速。

      【讨论】:

      • 这些函数是原子的吗?
      【解决方案7】:

      有趣的观察: 尝试通过各种 java 类复制同一个文件,并以纳秒为单位打印时间。

      使用 FileOutputStream 字节流的持续时间:4 965 078

      使用 BufferedOutputStream 的持续时间:1 237 206

      使用时长(字符文本阅读器:2 858 875

      使用 BufferedReader 的持续时间(缓冲字符文本流:1 998 005

      使用时间(文件 NIO 副本):18 351 115

      当使用 Files Nio 复制选项时,它花费的时间几乎是 18 倍!!! Nio 是复制文件最慢的选项,而 BufferedOutputStream 看起来是最快的。我对每个类都使用了相同的简单文本文件。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-12-29
        • 2020-02-20
        • 1970-01-01
        • 1970-01-01
        • 2015-10-28
        • 2014-06-25
        相关资源
        最近更新 更多