如何递归复制整个目录,包括Java中的父文件夹

时间:2012-07-25 14:20:17

标签: java directory

我目前正在将文件夹从一个地方复制到另一个地方。它工作正常,但它没有复制原始文件夹,所有其他文件和文件夹也在其中。这是我正在使用的代码:

public static void copyFolder(File src, File dest) throws IOException {
  if (src.isDirectory()) {
    //if directory not exists, create it
    if (!dest.exists()) {
      dest.mkdir();
    }
    //list all the directory contents
    String files[] = src.list();
    for (String file : files) {
      //construct the src and dest file structure
      File srcFile = new File(src, file);
      File destFile = new File(dest+"\\"+src.getName(), file);
      //recursive copy
      copyFolder(srcFile,destFile);
    }
  } else {
    //if file, then copy it
    //Use bytes stream to support all file types
    InputStream in = new FileInputStream(src);
    OutputStream out = new FileOutputStream(dest); 
    byte[] buffer = new byte[1024];
    int length;
    //copy the file content in bytes 
    while ((length = in.read(buffer)) > 0){
      out.write(buffer, 0, length);
    }
    in.close();
    out.close();
    System.out.println("File copied from " + src + " to " + dest);
  }
}

所以我有文件夹src C:\test\mytest\..all folders..

我想将其复制到C:\test\myfiles

但不是让C:\test\myfiles\mytest\..all folders..获得C:\test\myfiles\..all folders..

9 个答案:

答案 0 :(得分:8)

答案 1 :(得分:3)

有一个带有递归副本tutorial for copying files using java.nioexample code on Oracle Docs。它适用于java se 7+。它使用Files.walkFileTree方法,might cause some issues on ntfs with junction points。为避免使用Files.walkFileTree,可能的解决方案如下所示:

public static void copyFileOrFolder(File source, File dest, CopyOption...  options) throws IOException {
    if (source.isDirectory())
        copyFolder(source, dest, options);
    else {
        ensureParentFolder(dest);
        copyFile(source, dest, options);
    }
}

private static void copyFolder(File source, File dest, CopyOption... options) throws IOException {
    if (!dest.exists())
        dest.mkdirs();
    File[] contents = source.listFiles();
    if (contents != null) {
        for (File f : contents) {
            File newFile = new File(dest.getAbsolutePath() + File.separator + f.getName());
            if (f.isDirectory())
                copyFolder(f, newFile, options);
            else
                copyFile(f, newFile, options);
        }
    }
}

private static void copyFile(File source, File dest, CopyOption... options) throws IOException {
    Files.copy(source.toPath(), dest.toPath(), options);
}

private static void ensureParentFolder(File file) {
    File parent = file.getParentFile();
    if (parent != null && !parent.exists())
        parent.mkdirs();
} 

答案 2 :(得分:1)

您可以尝试Apache FileUtils复制目录

答案 3 :(得分:1)

您应该尝试apache commons FileUtils

答案 4 :(得分:1)

使用java.nio:

import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;

public static void copy(String sourceDir, String targetDir) throws IOException {

    abstract class MyFileVisitor implements FileVisitor<Path> {
        boolean isFirst = true;
        Path ptr;
    }

    MyFileVisitor copyVisitor = new MyFileVisitor() {

        @Override
        public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
            // Move ptr forward
            if (!isFirst) {
                // .. but not for the first time since ptr is already in there
                Path target = ptr.resolve(dir.getName(dir.getNameCount() - 1));
                ptr = target;
            }
            Files.copy(dir, ptr, StandardCopyOption.COPY_ATTRIBUTES);
            isFirst = false;
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
            Path target = ptr.resolve(file.getFileName());
            Files.copy(file, target, StandardCopyOption.COPY_ATTRIBUTES);
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
            throw exc;
        }

        @Override
        public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
            Path target = ptr.getParent();
            // Move ptr backwards
            ptr = target;
            return FileVisitResult.CONTINUE;
        }
    };

    copyVisitor.ptr = Paths.get(targetDir);
    Files.walkFileTree(Paths.get(sourceDir), copyVisitor);
}

答案 5 :(得分:1)

答案 6 :(得分:0)

主要问题是:

  dest.mkdir();

只创建一个目录,而不是父目录,在第一步之后,您需要创建两个目录,因此将mkdir替换为mkdirs。 在那之后,我猜你会因为你的递归(比如C:\ test \ myfiles \ mytest \ dir1 \ dir1 \ subdir1 \ subdir1 ...)而有重复的子目录,所以也试着解决这个问题:

    File destFile = new File(dest, src.getName());
    /**/
    OutputStream out = new FileOutputStream(new File(dest, src.getName())); 

答案 7 :(得分:0)

此代码将文件夹从源复制到目标:

    public static void copyDirectory(String srcDir, String dstDir)
    {

        try {
            File src = new File(srcDir);
            String ds=new File(dstDir,src.getName()).toString();
            File dst = new File(ds);

            if (src.isDirectory()) {
                if (!dst.exists()) {
                    dst.mkdir();
                }

                String files[] = src.list();
                int filesLength = files.length;
                for (int i = 0; i < filesLength; i++) {
                    String src1 = (new File(src, files[i]).toString());
                    String dst1 = dst.toString();
                    copyDirectory(src1, dst1);

                }
            } else {
                fileWriter(src, dst);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
public static void fileWriter(File srcDir, File dstDir) throws IOException
{
        try {
            if (!srcDir.exists()) {
                System.out.println(srcDir + " doesnot exist");
                throw new IOException(srcDir + " doesnot exist");
            } else {
                InputStream in = new FileInputStream(srcDir);
                OutputStream out = new FileOutputStream(dstDir);
                // Transfer bytes from in to out
                byte[] buf = new byte[1024];
                int len;
                while ((len = in.read(buf)) > 0) {
                    out.write(buf, 0, len);
                }
                in.close();
                out.close();

            }
        } catch (Exception e) {

        }
    }

答案 8 :(得分:0)

此解决方案非常简单,但是与平台无关,因为该命令以纯文本格式提供给操作系统。 (此示例适用于基于Unix的shell,对于Windows,该命令看上去与cp略有不同,称为copy。)

String source = "/user/.../testDir";
String destination = "/Library/.../testDestination/testDir";
String command = "cp -r " + source + " " + destination;
Process p;
try {
    p = Runtime.getRuntime().exec(command);
    p.waitFor();
} catch (InterruptedException | IOException e) {
    // Error handling
}

如果要将对象复制到具有相同名称的子文件夹中,请将其添加到目标路径中,否则将其省略,则文件夹内容将直接复制到目标路径中。

编辑:只是发现不幸的是,该解决方案不适用于网络驱动器。原因对我来说是未知的(但我承认我没有出于任何原因进行挖掘)