【问题标题】:Copy entire directory contents to another directory? [duplicate]将整个目录内容复制到另一个目录? [复制]
【发布时间】:2011-09-07 01:36:33
【问题描述】:

在java或groovy中将整个目录内容复制到另一个目录的方法?

【问题讨论】:

  • 你想要一个命令行工具或代码?

标签: java grails file-io groovy


【解决方案1】:

FileUtils.copyDirectory()

复制整个目录 到保存文件的新位置 日期。该方法复制 指定目录及其所有子目录 目录和文件到指定 目的地。目的地是 新的位置和名称 目录。

目标目录已创建 如果它不存在。如果 目标目录确实存在,那么 此方法将源与 目的地,源头 优先级。

为此,这里是示例代码

String source = "C:/your/source";
File srcDir = new File(source);

String destination = "C:/your/destination";
File destDir = new File(destination);

try {
    FileUtils.copyDirectory(srcDir, destDir);
} catch (IOException e) {
    e.printStackTrace();
}

【讨论】:

  • 在我的情况下,我有一些子文件夹,我也想复制结构,并找到方法FileUtils.copyDirectoryStructure()。也许这对其他人也有帮助。
  • JAVA API NIO 2 怎么样?我试过Files.copy(Path, Path),但它似乎没有做同样的工作。
  • @Ethan Leroy copyDirectoryStructure 和 copyDirectory 有什么区别?
  • 这里可以看到“目录可以复制,但是目录里面的文件没有复制,所以新目录是空的”docs.oracle.com/javase/tutorial/essential/io/copy.html
  • import org.apache.commons.io.FileUtils
【解决方案2】:

以下是使用JDK7的示例。

public class CopyFileVisitor extends SimpleFileVisitor<Path> {
    private final Path targetPath;
    private Path sourcePath = null;
    public CopyFileVisitor(Path targetPath) {
        this.targetPath = targetPath;
    }

    @Override
    public FileVisitResult preVisitDirectory(final Path dir,
    final BasicFileAttributes attrs) throws IOException {
        if (sourcePath == null) {
            sourcePath = dir;
        } else {
        Files.createDirectories(targetPath.resolve(sourcePath
                    .relativize(dir)));
        }
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult visitFile(final Path file,
    final BasicFileAttributes attrs) throws IOException {
    Files.copy(file,
        targetPath.resolve(sourcePath.relativize(file)));
    return FileVisitResult.CONTINUE;
    }
}

要使用访问者,请执行以下操作

Files.walkFileTree(sourcePath, new CopyFileVisitor(targetPath));

如果您宁愿将所有内容都内联(如果您经常使用它,效率不会太高,但对快手有好处)

    final Path targetPath = // target
    final Path sourcePath = // source
    Files.walkFileTree(sourcePath, new SimpleFileVisitor<Path>() {
        @Override
        public FileVisitResult preVisitDirectory(final Path dir,
                final BasicFileAttributes attrs) throws IOException {
            Files.createDirectories(targetPath.resolve(sourcePath
                    .relativize(dir)));
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult visitFile(final Path file,
                final BasicFileAttributes attrs) throws IOException {
            Files.copy(file,
                    targetPath.resolve(sourcePath.relativize(file)));
            return FileVisitResult.CONTINUE;
        }
    });

【讨论】:

  • 这个工作实际上有一位预言家的访问者:docs.oracle.com/javase/tutorial/essential/io/examples/Copy.java - 和你的有什么不同?
  • 我的只是复制文件,他们是一个完整的应用程序,带有属性复制。
  • 非常好的解决方案!我将向其他读者指出这种方法的一个不那么明显的优势。如果您使用 jar FileSystem 路径,此方法可用于将文件复制到 jar 中和从 jar 中复制出来。
【解决方案3】:

使用 Groovy,您可以leverage Ant 做:

new AntBuilder().copy( todir:'/path/to/destination/folder' ) {
  fileset( dir:'/path/to/src/folder' )
}

AntBuilder 是分发和自动导入列表的一部分,这意味着它可直接用于任何 groovy 代码。

【讨论】:

  • 在Java中你可能可以,但这就像用大锤敲碎核桃。
  • 也许,但在 groovy 中 AntBuilder 是分发和自动导入列表的一部分,这意味着它可直接用于答案中所写的任何 groovy 代码。
【解决方案4】:
public static void copyFolder(File source, File destination)
{
    if (source.isDirectory())
    {
        if (!destination.exists())
        {
            destination.mkdirs();
        }

        String files[] = source.list();

        for (String file : files)
        {
            File srcFile = new File(source, file);
            File destFile = new File(destination, file);

            copyFolder(srcFile, destFile);
        }
    }
    else
    {
        InputStream in = null;
        OutputStream out = null;

        try
        {
            in = new FileInputStream(source);
            out = new FileOutputStream(destination);

            byte[] buffer = new byte[1024];

            int length;
            while ((length = in.read(buffer)) > 0)
            {
                out.write(buffer, 0, length);
            }
        }
        catch (Exception e)
        {
            try
            {
                in.close();
            }
            catch (IOException e1)
            {
                e1.printStackTrace();
            }

            try
            {
                out.close();
            }
            catch (IOException e1)
            {
                e1.printStackTrace();
            }
        }
    }
}

【讨论】:

  • 它是 Groovy 吗?它看起来比 Java 更像 C++。 :-)。但这似乎是正确的。 +1。如果我们正在复制并同时对正在复制的文本进行一些工作,那就太好了。
  • 工作,简单,好!此解决方案与其他解决方案之间的唯一区别可能是副本的修改日期和创建日期设置为当前时间,但有时这就是您想要的。
  • 称我为老式的,但很高兴在新行上看到大括号。我是一名前 C 和 C++ 程序员,尽管我已经用 Java 编写了 20 年,但我仍然编写这样的代码。更具可读性!
  • 我认为这是更清晰的方法。进度条呢?
  • 救命稻草我在 kotlin WORKS PERFECT +2 中使用它
【解决方案5】:

这是我的一段 Groovy 代码。经测试。

private static void copyLargeDir(File dirFrom, File dirTo){
    // creation the target dir
    if (!dirTo.exists()){
        dirTo.mkdir();
    }
    // copying the daughter files
    dirFrom.eachFile(FILES){File source ->
        File target = new File(dirTo,source.getName());
        target.bytes = source.bytes;
    }
    // copying the daughter dirs - recursion
    dirFrom.eachFile(DIRECTORIES){File source ->
        File target = new File(dirTo,source.getName());
        copyLargeDir(source, target)
    }
}

【讨论】:

  • 这比FileUtils.copyDirectory()好多少?
  • @doelleri 有两点更好 - 我不需要安装任何额外的 jar 或在 Maven 中放置引用,为版本而苦苦挣扎。顺便说一句,那个“答案”应该有适当的包含行和对 jar 的引用。第二个原因 - 如果我想在子目录中进行一些严格的过滤,只有我的代码会有所帮助。第三个原因 - 这里是程序员的网站,而不仅仅是软件用户。 :-)
  • 如果您想知道这些文件的来源,可以将 FILES 替换为 groovy.io.FileType.FILES 并将 DIRECTORIES 替换为 groovy.io.FileType.DIRECTORIES。
【解决方案6】:

【讨论】:

  • 澄清“Java 7:看看 java.nio.file.Files”——实际上并没有回答问题
  • 虽然Files.copy 支持目录,但它不会复制目录的内容。
  • apache 是最好的。 +1
  • @OhadR 我会说更简单,而不是“更好”。
【解决方案7】:

随着Java NIO的到来,下面也是一个可能的解决方案

使用 Java 9:

private static void copyDir(String src, String dest, boolean overwrite) {
    try {
        Files.walk(Paths.get(src)).forEach(a -> {
            Path b = Paths.get(dest, a.toString().substring(src.length()));
            try {
                if (!a.toString().equals(src))
                    Files.copy(a, b, overwrite ? new CopyOption[]{StandardCopyOption.REPLACE_EXISTING} : new CopyOption[]{});
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    } catch (IOException e) {
        //permission issue
        e.printStackTrace();
    }
}

使用 Java 7:

import java.io.IOException;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.function.Consumer;
import java.util.stream.Stream;

public class Test {

    public static void main(String[] args) {
        Path sourceParentFolder = Paths.get("/sourceParent");
        Path destinationParentFolder = Paths.get("/destination/");

        try {
            Stream<Path> allFilesPathStream = Files.walk(sourceParentFolder);
            Consumer<? super Path> action = new Consumer<Path>(){

                @Override
                public void accept(Path t) {
                    try {
                        String destinationPath = t.toString().replaceAll(sourceParentFolder.toString(), destinationParentFolder.toString());
                        Files.copy(t, Paths.get(destinationPath));
                    } 
                    catch(FileAlreadyExistsException e){
                        //TODO do acc to business needs
                    }
                    catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }

                }

            };
            allFilesPathStream.forEach(action );

        } catch(FileAlreadyExistsException e) {
            //file already exists and unable to copy
        } catch (IOException e) {
            //permission issue
            e.printStackTrace();
        }

    }

}

【讨论】:

  • 为什么投反对票..?如果需要改进,请提出建议。
  • 字符串替换可能会导致意想不到的副作用。您应该只替换我们知道存在的最开始,并且我们知道它的长度,所以您可以使用:Paths.get(dest, a.toString().substring(src.length()))。此外,您还可以进行一些优化:可以删除重复的 FileAlreadyExistsException 子句,源和目标 Path 对象只有一种用法,因此无需为每个对象设置一个 var
  • 同意,谢谢@Charlie
  • 我会建议将一些样板文件换成 lambda,但这会伤害寻找 Java 7 (6?) 答案的人。
  • 我打算添加我自己的答案,但这个问题作为一个骗子被关闭了(即使它不是)。我将使用我的 Java 9 版本添加到您的答案中。不喜欢就删掉;)
【解决方案8】:

FileUtils.copyDirectory()Archimedes's answer 都不会复制目录属性(文件所有者、权限、修改时间等)。

https://stackoverflow.com/a/18691793/14731 提供了一个完整的 JDK7 解决方案,正是这样做的。

【讨论】:

【解决方案9】:

关于Java,标准API中没有这样的方法。在 Java 7 中,java.nio.file.Files 类将提供 copy 便利方法。

参考文献

  1. The Java Tutorials

  2. Copying files from one directory to another in Java

【讨论】:

  • Files.copy 不支持复制目录内容。
【解决方案10】:

如果您愿意使用第 3 方库,请查看 javaxt-core。 javaxt.io.Directory 类可以用来复制这样的目录:

javaxt.io.Directory input = new javaxt.io.Directory("/source");
javaxt.io.Directory output = new javaxt.io.Directory("/destination");
input.copyTo(output, true); //true to overwrite any existing files

您还可以提供文件过滤器来指定要复制的文件。这里还有更多例子:

http://javaxt.com/javaxt-core/io/Directory/Directory_Copy

【讨论】:

  • 但是如何将它添加到android项目中?依赖在哪里?
猜你喜欢
  • 1970-01-01
  • 2014-07-18
  • 1970-01-01
  • 2013-01-11
  • 2020-09-06
  • 1970-01-01
  • 2012-09-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多