欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

[NIO.2] 第三十六篇 编写一个文件拷贝应用

程序员文章站 2024-01-04 19:15:21
...
拷贝目录树的时候,需要为文件和目录递归调用 Files.copy() 方法。在开始编写代码之前,要注意以下几点:

[list]
[*]在拷贝目录中的文件之前,必须先拷贝目录本身。不管目录中是否有文件,拷贝目录后的结果都将是空目录。这个任务必须在 preVisitDirectory() 中完成。
[*]拷贝文件最好在 visitFile() 方法中进行。
[*]在拷贝文件或目录的过程中,你要考虑是否需要使用 REPLACE_EXISTING 和 COPY_ATTRIBUTES 配置项。
[*]如果你需要保留目录的属性,那么要等到文件拷贝完成后在 postVisitDirectory() 方法中进行操作。
[*]如果你选择了使用目标文件处理软链接(FOLLOW_LINKS),并且在目录树中有循环引用,那么将会触发 visitFileFailed() 方法并抛出 FileSystemLoopException 异常。
[*]如果没有权限访问文件,那么visitFileFailed() 方法需要返回FileVisitResult.CONTINUE 或 TERMINATE,具体返回什么根据你的需求决定。
[*]在拷贝过程中,可以用 FOLLOW_LINKS 选项来用目标文件处理软链接。
[/list]

下面的代码将演示将 C:\rafaelnadal 子目录树拷贝到 C:\rafaelnadal_copy 中:

import java.nio.file.FileSystemLoopException; 
import java.nio.file.attribute.FileTime;
import java.io.IOException;
import java.nio.file.FileVisitOption;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.EnumSet;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
import static java.nio.file.StandardCopyOption.COPY_ATTRIBUTES;

class CopyTree implements FileVisitor {

private final Path copyFrom;
private final Path copyTo;

public CopyTree(Path copyFrom, Path copyTo) {
this.copyFrom = copyFrom;
this.copyTo = copyTo;
}

static void copySubTree(Path copyFrom, Path copyTo) throws IOException {
try {
Files.copy(copyFrom, copyTo, REPLACE_EXISTING, COPY_ATTRIBUTES);
} catch (IOException e) {
System.err.println("Unable to copy " + copyFrom + " [" + e + "]");
}

}

@Override
public FileVisitResult postVisitDirectory(Object dir, IOException exc)
throws IOException {
if (exc == null) {
Path newdir = copyTo.resolve(copyFrom.relativize((Path) dir));
try {
FileTime time = Files.getLastModifiedTime((Path) dir);
Files.setLastModifiedTime(newdir, time);
} catch (IOException e) {
System.err.println("Unable to copy all attributes to: " + newdir+" ["+e+ "]");
}
} else {
throw exc;
}

return FileVisitResult.CONTINUE;
}

@Override
public FileVisitResult preVisitDirectory(Object dir, BasicFileAttributes attrs)
System.out.println("Copy directory: " + (Path) dir);
Path newdir = copyTo.resolve(copyFrom.relativize((Path) dir));
try {
Files.copy((Path) dir, newdir, REPLACE_EXISTING, COPY_ATTRIBUTES);
} catch (IOException e) {
System.err.println("Unable to create " + newdir + " [" + e + "]");
return FileVisitResult.SKIP_SUBTREE;
}

return FileVisitResult.CONTINUE;
}

@Override
public FileVisitResult visitFile(Object file, BasicFileAttributes attrs)
throws IOException {
System.out.println("Copy file: " + (Path) file);
copySubTree((Path) file, copyTo.resolve(copyFrom.relativize((Path) file)));
return FileVisitResult.CONTINUE;
}

@Override
public FileVisitResult visitFileFailed(Object file, IOException exc)
throws IOException {
if (exc instanceof FileSystemLoopException) {
System.err.println("Cycle was detected: " + (Path) file);
} else {
System.err.println("Error occurred, unable to copy:" +(Path) file+" ["+ exc +
"]");
}

return FileVisitResult.CONTINUE;
}
}

class Main {

public static void main(String[] args) throws IOException {

Path copyFrom = Paths.get("C:/rafaelnadal");
Path copyTo = Paths.get("C:/rafaelnadal_copy");

CopyTree walk = new CopyTree(copyFrom, copyTo);
EnumSet opts = EnumSet.of(FileVisitOption.FOLLOW_LINKS);

Files.walkFileTree(copyFrom, opts, Integer.MAX_VALUE, walk);
}
}


运行了上面的代码后,你将发现 C:\rafaelnadal_copy 和 C:\rafaelnadal 将会有完全一样的目录树和属性。

文章来源:[url]http://www.aptusource.org/2014/04/nio-2-writing-a-copy-files-application/[/url]
相关标签: java NIO.2

上一篇:

下一篇: