【问题标题】:How to copy a directory with its attributes/permissions from one location to another?如何将具有属性/权限的目录从一个位置复制到另一个位置?
【发布时间】:2013-07-12 13:51:48
【问题描述】:

我看到很多examples 使用Files.walkFileTree() 将目录及其内容从一个位置复制到另一个位置,但他们没有考虑到目录的文件属性和权限。意思是,他们只是调用Files.createDirectories(),没有任何属性或权限。

如何使用 Java7 核心类将目录(及其内容)从一个位置复制到另一个位置而不丢失文件属性或权限?

【问题讨论】:

标签: java-7 nio2


【解决方案1】:

回答我自己的问题:

/**
 * Copies a directory.
 * <p>
 * NOTE: This method is not thread-safe.
 * <p>
 * 
 * @param source
 *            the directory to copy from
 * @param target
 *            the directory to copy into
 * @throws IOException
 *             if an I/O error occurs
 */
private static void copyDirectory(final Path source, final Path target)
        throws IOException {
    Files.walkFileTree(source, EnumSet.of(FileVisitOption.FOLLOW_LINKS),
        Integer.MAX_VALUE, new FileVisitor<Path>() {

            @Override
            public FileVisitResult preVisitDirectory(Path dir,
                    BasicFileAttributes sourceBasic) throws IOException {
                Path targetDir = Files.createDirectories(target
                    .resolve(source.relativize(dir)));
                AclFileAttributeView acl = Files.getFileAttributeView(dir,
                    AclFileAttributeView.class);
                if (acl != null)
                    Files.getFileAttributeView(targetDir,
                        AclFileAttributeView.class).setAcl(acl.getAcl());
                DosFileAttributeView dosAttrs = Files.getFileAttributeView(
                    dir, DosFileAttributeView.class);
                if (dosAttrs != null) {
                    DosFileAttributes sourceDosAttrs = dosAttrs
                        .readAttributes();
                    DosFileAttributeView targetDosAttrs = Files
                        .getFileAttributeView(targetDir,
                            DosFileAttributeView.class);
                    targetDosAttrs.setArchive(sourceDosAttrs.isArchive());
                    targetDosAttrs.setHidden(sourceDosAttrs.isHidden());
                    targetDosAttrs.setReadOnly(sourceDosAttrs.isReadOnly());
                    targetDosAttrs.setSystem(sourceDosAttrs.isSystem());
                }
                FileOwnerAttributeView ownerAttrs = Files
                    .getFileAttributeView(dir, FileOwnerAttributeView.class);
                if (ownerAttrs != null) {
                    FileOwnerAttributeView targetOwner = Files
                        .getFileAttributeView(targetDir,
                            FileOwnerAttributeView.class);
                    targetOwner.setOwner(ownerAttrs.getOwner());
                }
                PosixFileAttributeView posixAttrs = Files
                    .getFileAttributeView(dir, PosixFileAttributeView.class);
                if (posixAttrs != null) {
                    PosixFileAttributes sourcePosix = posixAttrs
                        .readAttributes();
                    PosixFileAttributeView targetPosix = Files
                        .getFileAttributeView(targetDir,
                            PosixFileAttributeView.class);
                    targetPosix.setPermissions(sourcePosix.permissions());
                    targetPosix.setGroup(sourcePosix.group());
                }
                UserDefinedFileAttributeView userAttrs = Files
                    .getFileAttributeView(dir,
                        UserDefinedFileAttributeView.class);
                if (userAttrs != null) {
                    UserDefinedFileAttributeView targetUser = Files
                        .getFileAttributeView(targetDir,
                            UserDefinedFileAttributeView.class);
                    for (String key : userAttrs.list()) {
                        ByteBuffer buffer = ByteBuffer.allocate(userAttrs
                            .size(key));
                        userAttrs.read(key, buffer);
                        buffer.flip();
                        targetUser.write(key, buffer);
                    }
                }
                // Must be done last, otherwise last-modified time may be
                // wrong
                BasicFileAttributeView targetBasic = Files
                    .getFileAttributeView(targetDir,
                        BasicFileAttributeView.class);
                targetBasic.setTimes(sourceBasic.lastModifiedTime(),
                    sourceBasic.lastAccessTime(),
                    sourceBasic.creationTime());
                return FileVisitResult.CONTINUE;
            }

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

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

            @Override
            public FileVisitResult postVisitDirectory(Path dir,
                    IOException e) throws IOException {
                if (e != null) throw e;
                return FileVisitResult.CONTINUE;
            }
        });
}

此代码尚未经过广泛测试,但对我有用。

【讨论】:

  • 两个问题:1. 为什么不是原版的:docs.oracle.com/javase/tutorial/essential/io/examples/Copy.java 2. 为什么不是 SimpleFileVisitor 的实现
  • 该设计还可以从一个枚举中受益,该枚举将在其构造函数中接受 Class
  • @Mr_and_Mrs_D,“普通版”复制属性但不复制权限。您认为哪条线路会这样做?
  • @Mr_and_Mrs_D,我不明白你对枚举和构造函数的意思。 Class&lt;T extends FileAttributeView&gt; 不是enum,也不清楚你指的是什么构造函数。
  • 回复:枚举:dropbox.com/s/ngrwqnhzx7o7iqu/CopyDirectory.java。回复:香草一号 - 只是在问,我现在明白了。请注意,我将匿名类更改为嵌套并使其实现 SimpleFileVisitor(如 visitFileFailed 和 postVisitDirectory)在您的匿名实现中具有默认行为
猜你喜欢
  • 2014-11-26
  • 1970-01-01
  • 2014-11-25
  • 2014-02-04
  • 2013-05-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多