最后更新:2015-04-15
这个Java NIO的Files类(java.nio.file.Files)提供了数个方法中文件系统中操作文件。这个Java NIO的Files类教程将会覆盖这些方法的大部分通用方法的使用。这个类包含了许多的方法,所以也可以核对这个JavaDoc,如果你需要一个没有在这里描述的方法。这个Files类只是可能为了它仍然有一个方法。
这个java.nio.file.Files类同java.nio.file.Path实例一起工作,以至于你在同Files类工作之前需要理解这个Path类。
Files.exists()
这个方法检查给予的这个路径是否在这个文件中。
去创建一个在文件系统不存在的Path实例是可能的。例如,如果你计划创建一个新的目录,你将会首先创建相应的Path实例,然后创建这个目录。
因为Path实例可能指向或者可能没有指向存在这个文件系统的路径,你可以使用Files.exists()方法去决定是否他们是(一旦你需要检查那个)。
这里有一个Java的Files.exists()实例:
Path path = Paths.get("data/logging.properties");
boolean pathExists =
Files.exists(path,
new LinkOption[]{ LinkOption.NOFOLLOW_LINKS});
注意Files.exists的第二个参数。这个参数是一个数组选项,它影响着这个Files.exists是怎么决定文件路径是否存在。在上面的这个例子中,这个数组包括这个LinkOption.NOFOLLOW_LINKS,这个意味着这个Files.exists方法应该不会跟随这个文件系统的符号链接去决定路径是否存在。
Files.createDirectory()
这个方法创建一个来自于Path实例的一个新的目录。这里有一个例子:
Path path = Paths.get("data/subdir");
try {
Path newDir = Files.createDirectory(path);
} catch(FileAlreadyExistsException e){
// the directory already exists.
} catch (IOException e) {
//something else went wrong
e.printStackTrace();
}
第一行创建了一个将会去创建的一个目录的Path实例。在try-catch块内部的这个Files.createDirectory()方法使用这个path作为一个参数被调用。如果创建一个目录成功,一个执行这个新创建的路径的Path实例被返回。
如果这个目录已经存在了,一个java.nio.file.FileAlreadyEXistsException将会抛出。如果其他的出现错误的话,一个IOException可能会抛出,例如,如果所期望的上级目录,新目录不存在的话,一个IOException会抛出。这个上级目录是你想创建的那个新的目录。因此,它意味着这个新目录的上级目录。
Files.copy()
这个方法拷贝一个文件从一个路径到另外一个。这里有一个例子:
Path sourcePath = Paths.get("data/logging.properties");
Path destinationPath = Paths.get("data/logging-copy.properties");
try {
Files.copy(sourcePath, destinationPath);
} catch(FileAlreadyExistsException e) {
//destination file already exists
} catch (IOException e) {
//something else went wrong
e.printStackTrace();
}
如果这个目的文件已经存在,一个java.nio.file.FileAlreadyEXistsException将会抛出。如果其他的事情出现错误,一个IOException会抛出。例如,如果拷贝文件的这个目录不存在,将会抛出一个IOException。
覆盖已经存在的文件
强制的Files.copy()去覆盖已经存在的文件是可能的。这里有一个例子展示怎样通过Files.copy()方法去覆盖已经存在的文件:
Path sourcePath = Paths.get("data/logging.properties");
Path destinationPath = Paths.get("data/logging-copy.properties");
try {
Files.copy(sourcePath, destinationPath,
StandardCopyOption.REPLACE_EXISTING);
} catch(FileAlreadyExistsException e) {
//destination file already exists
} catch (IOException e) {
//something else went wrong
e.printStackTrace();
}
Files.move()
这个Java NIO类也包含了一个这样的函数,移动一个文件从一个路径到另外一个路径。移动一个文件就像重命名它一样,移动一个文件既可以移动到不同的目录,还可以同时改变他的名字。是的,这个java.io.File类的renameTo()方法也可以做这个事情,但是现在你也可以在java.nio.file.Files类中做文件移动的功能。
这里有一个例子:
Path sourcePath = Paths.get("data/logging-copy.properties");
Path destinationPath = Paths.get("data/subdir/logging-moved.properties");
try {
Files.move(sourcePath, destinationPath,
StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
//moving file failed.
e.printStackTrace();
}
注意这个方法里面的第三个参数,这个参数告诉这个方法将会覆盖目的路径中任何存在的文件。这个参数实际上是可选择的。
如果移动文件失败可能会抛出IOException异常。例如,如果一个文件已经存在目的路径中,并且你遗漏了StandardCopyOption.REPLACE_EXISTING这个选项,或者将要移动的这个文件不存在等等。
Files.delete()
这个方法可以删除一个文件或者一个目录。这里有一个例子:
Path path = Paths.get("data/subdir/logging-moved.properties");
try {
Files.delete(path);
} catch (IOException e) {
//deleting file failed
e.printStackTrace();
}
Files.walkFileTree()
这个方法包含了可以递归遍历一个目录树的功能。这个方法携带着一个Path实例和FileVisitor作为参数。这个Path实例指向了你想要遍历的目录。这个FileVisitor是中遍历期间被调用。
在我解释这个遍历是如何工作的之前,这里首先有一个FileVisitor接口:
public interface FileVisitor {
public FileVisitResult preVisitDirectory(
Path dir, BasicFileAttributes attrs) throws IOException;
public FileVisitResult visitFile(
Path file, BasicFileAttributes attrs) throws IOException;
public FileVisitResult visitFileFailed(
Path file, IOException exc) throws IOException;
public FileVisitResult postVisitDirectory(
Path dir, IOException exc) throws IOException {
}
你不得不自己去实现FileVisitor接口,以及传递你实现的一个实例到walkFileTree方法中。你的FileVisitor实现的每一个方法中目录遍历期间的不同时间将会被调用。如果你不想去实现这些所有的方法,你可以继承SimpleFileVisitor类,这个类里面包含了FileVisitor接口所有方法的默认实现。
这里有一个walkFileTree的例子:
Files.walkFileTree(path, new FileVisitor() {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
System.out.println("pre visit dir:" + dir);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
System.out.println("visit file: " + file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
System.out.println("visit file failed: " + file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
System.out.println("post visit directory: " + dir);
return FileVisitResult.CONTINUE;
}
});
这个preVisitDirectory()
方法将会中访问任何目录之前会被调用。这个 postVisitDirectory()
方法是中访问目录之后被调用。
这个visitFile()方法是中每一个文件访问期间会被调用,它对于目录是不会被调用的--只是相对文件。这个visitFileFailed()方法一旦访问文件失败将会被调用。例如,如果你没有正确的权限,或者是其他事情出错了。
四个方法中的每一个都返回了一个FileVisitResult
枚举实例。这个枚举实例包含下面四个选项:
preVisitDirectory()
返回就会有这个功能。如果从其他任何方法返回,他将会作为一个CONTINUE被解释使用。
SimpleFileVisitor
去寻找README.txt的文件:
Path rootPath = Paths.get("data");
String fileToFind = File.separator + "README.txt";
try {
Files.walkFileTree(rootPath, new SimpleFileVisitor() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
String fileString = file.toAbsolutePath().toString();
//System.out.println("pathString = " + fileString);
if(fileString.endsWith(fileToFind)){
System.out.println("file found at path: " + file.toAbsolutePath());
return FileVisitResult.TERMINATE;
}
return FileVisitResult.CONTINUE;
}
});
} catch(IOException e){
e.printStackTrace();
}
Path rootPath = Paths.get("data/to-delete");
try {
Files.walkFileTree(rootPath, new SimpleFileVisitor() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
System.out.println("delete file: " + file.toString());
Files.delete(file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
Files.delete(dir);
System.out.println("delete dir: " + dir.toString());
return FileVisitResult.CONTINUE;
}
});
} catch(IOException e){
e.printStackTrace();
}
翻译地址:http://tutorials.jenkov.com/java-nio/files.html