Java中的移动/复制文件操作


70

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

Answers:


72

这是通过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();
        }
    }
}

5
如果文件存在,内容将被追加还是覆盖?
Janusz,2009年

@Rigo这仅移动文件,我无法移动目录
Arasu

11
值得注意的是Java 7具有更简单的复制/移动方法
塔文(Tharwen)2012年

2
有什么原因File.renameTo不如Files.move
埃里克·卡普伦2014年

4
@Erik Allik:如果操作失败,Files.move将告诉您原因,而不是简单地返回false。并且Files.move可以处理不是简单重命名的移动,即需要复制和删除。
Holger 2014年

40

尚未,但是New NIO(JSR 203)将支持这些常见操作。

同时,有几点需要牢记。

File.renameTo通常仅适用于同一文件系统卷。我认为这等效于“ mv”命令。如果可以的话,请使用它,但要获得常规的复制和移动支持,您将需要一个备用。

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


17

检出:http : //commons.apache.org/io/

它具有副本,并且如前所述,JDK已移动。

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


Commons IO在可以复制的文件大小方面有限制。对于通用解决方案,可以预期会有更强大的实现。
erickson

3
实现自己的复制方法很简单,这意味着您将不必依赖整个库。不要实现自己的
oxbow_lakes

17
复制方法绝非易事。您可以轻松地制作出不使用Streams可以正确执行的操作,而使用NIO可以快速但不正确地执行操作。当有质量库时,切勿实现自己的实用程序。
Pyrolistical

3
复制方法非易事,Apache Commons无法处理一个常见用例:信息对于主内存而言太大。旨在管理大容量存储的库应限制其内存消耗,而Apache Commons move方法缺少该内存消耗。
erickson

@PyrolisticalNever implement your own utilities when there are quality libraries out there.嗯,如果您永远不必担心许可问题。
b1nary.atr0phy

10

先前的答案似乎已过时。

Java的File.renameTo()可能是API 7最简单的解决方案,并且似乎工作正常。请注意,它不会抛出异常,但会返回true / false!

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

如果您需要使用以前的版本,请在此处检查。

这是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);

3
如果在第二段代码中出现“该进程无法访问该文件,因为该文件正在被另一个进程使用。”该进程无法访问该文件,因为该文件正在被另一个进程使用。”,请记住关闭该文件在移动之前.....
ntg 2012年

2
在其他意外情况下,它也会失败,例如,在Linux上,如果在/ mnt / a / mnt / b下安装了两个不同的文件系统,则无法将文件/ mnt / a / file1重命名为/ mnt / b / file2,因为它实际上是一个移动操作,在这种情况下File.renameTo将失败。
xask 2013年

1
这是最好的解决方案。如果您担心重命名操作失败,只需使用Files.move()即可。
xtian


7

尝试使用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) =>将文件或目录移动到目标目录。

简单,轻松,快速。


这些功能是原子的吗?
Sumit 2015年

0

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

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

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

使用的持续时间(字符文本阅读器:2 858 875

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

使用的持续时间(文件NIO副本):18351115

当使用文件Nio复制选项时,它花费了将近18倍的时间!Nio是复制文件的最慢选项,而BufferedOutputStream看起来是最快的。我为每个班级使用了相同的简单文本文件。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.