Java NIO系列教程(十六) Java NIO Files
原文地址 译者:章筱虎
java NIO Files类(java.nio.file.Files) 提供了操作文件的相关方法。本篇文章将会覆盖大多数常用的方法。Files类包含了很多方法,如果你需要的功能在文中没有提及,需要自己查阅JavaDoc文档确认,也许Files类提供了相应方法(译者注:但本文中没有涉及)
java.nio.file.Files类需要和java.nio.file.Path一起使用,在学习Files类前,你需要掌握Path类的相关用法。
Files.exists()
Files.exists()方法用来检查文件系统中是否存在某路径。
Path实例对应的路径可能在文件系统中并不存在。例如,如果打算新建一个文件夹,首先需要创建一个对应的Path实例,然后才能创建对应路径下的文件夹。
因为Path实例对应的路径在文件系统的存在性不确定,可以使用Files.exists()方法确认Path对应的路径是否存在 (也就是开发需要自己显式的去调用该方法确认)。
如下是Files.exists()的示例:
Path path = Paths.get("data/logging.properties"); boolean pathExists = Files.exists(path, new LinkOption[]{ LinkOption.NOFOLLOW_LINKS});
示例中首先创建了一个Path。然后,通过调用Files.exists方法并将path作为第一个参数确认path对应的路径是否存在。
注意下Files.exist()方法的第二个参数。第二个参数数组是评判路径是否存在时使用的规则。示例中,数组包含LinkOption.NOFOLLOW_LINKS枚举类型,表示Files.exists不会跟进到路径中有连接的下层文件目录。表示path路径中如果有连接,Files.exists方法不会跟进到连接中去
原创文章,转载请注明: 转载自并发编程网 – ifeve.com本文链接地址: Java NIO系列教程(十六) Java NIO Files
貌似没有翻译完?
Files.walkFileTree()是个遍历文件系统的好工具,就是不能并发执行太可惜了。
补充翻译部分:
Files.createDirectory()方法
Files.createDirectory()基于Path实例创建目录,如下例:
Path path = Paths.get(“data/subdir”);
try {
Path newDir = Files.createDirectory(path);
} catch(FileAlreadyExistsException e){
// 处理文件已存在的异常.
} catch (IOException e) {
//处理其它异常
e.printStackTrace();
}
第一行创建代表对应目录的Path对象(实例,对象即实例,不再赘述),try-catch块中的Files.createDirectory(path)将第一行创建的path对象最为参数执行创建操作。如果创建成功,方法返回代表目录的path对象,
如果要创建的目录已经存在,将抛出 FileAlreadyExistsException 异常。如果执行过程中有其他问题,如:要创建目录的父目录不存在,则会抛出 IOException 异常。
Files.copy()方法
Files.copy()方法将 源path对象指向的 文件按照目标path指定名称拷贝到目标path指向的目录下。如下例:
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();
}
例子中,首先创建 源path对象 和 目标path对象,然后将这两个path对象作为参数,调用Files.copy()方法。就会将源path指向的文件按照目标path指定名称拷贝到目标path指向目录下。
如果目标path指向的文件已经存在,将抛出 java.nio.file.FileAlreadyExistsException 异常。如果执行过程中有其他问题,如:要拷贝的文件不存在,则会抛出 IOException 异常。
覆盖已存在文件(Overwriting Existing Files)
如果目标文件存在,调用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.copy() 的第三个参数 StandardCopyOption.REPLACE_EXISTING,它表示如果目标文件存在,则将其覆盖。
Files.move()方法
JAVA NIO Files 类中也有移动文件到目标路径的方法。移动文件与重命名文件一样,只是NIO 可以通过调用Files.move()完成移动和重命名两项操作。确实,java.io.File 类也可以通过其renameTo()方法完成上述功能,不过,现在你也可以使用NIO中的 java.nio.file.Files 类。
Files.move()方法,如下例:
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();
}
例子中,首先创建源path(sourcePath) 和目标path(destinationPath),源path指向要被移动的文件,目标path指向要移动到位置和名称。调用Files.move()方法后,文件将被移动。
注意Files.move()中的第三个参数 StandardCopyOption.REPLACE_EXISTING,它表示移动过程中,如果目标文件存在,则覆盖它。这个选项为可选项。
移动文件失败可能会触发IOException,比如:目标文件存在,而我们没有使用 StandardCopyOption.REPLACE_EXISTING 可选项。或者源文件不存在等。
Files.walkFileTree()
Files.walkFileTree()方法具备递归遍历目录树的功能。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实现类的全部方法会在目录遍历的过程中被调用。如果不想实现FileVisitor接口的全部方法,也可以直接继承 SimpleFileVisitor 类,这个类提供了 FileVisitor 接口全部方法的默认实现。
接下来看看Files.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;
}
});
FileVisitor实现类的方法会在目录遍历的不同阶段被调用。
访问每个目录前,都会先调用 preVisitDirectory()方法 ,访问目录之后会调用postVisitDirectory()方法。
文件遍历期间访问每个文件,都会调用visitFile()方法。这个方法只在遍历文件时调用,遍历目录时不调用。
遍历文件失败时,会调用visitFileFailed() 方法。比如,程序没有正确的权限或者其它问题。
FileVisitor实现类方法都会返回 FileVisitResult 枚举实例。FileVisitResult 枚举包含以下四项:
CONTINUE
TERMINATE
SKIP_SIBLINGS
SKIP_SUBTREE
根据返回的不同枚举值,Files.walkFileTree()会采取不同的方式执行后续遍历。
CONTINUE:表示文件遍历将按默认方式继续。
TERMINATE:表示终止遍历。
SKIP_SIBLINGS:表示跳过当前同级的目录和文件,继续遍历。
SKIP_SUBTREE:表示跳过当前目录的子节点,继续遍历。这个枚举值只在作为preVisitDirectory()返回值时生效,如果作为其他方法的返回值,则会被视为CONTINUE。
查找文件(Searching For Files)
下面是一个继承自 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();
}
递归删除目录(Deleting Directories Recursively)
Files.walkFileTree()方法也可以用于删除目录(包括目录包含的文件及子目录)。Files.delete()方法只能删除文件和空目录,但可以结合Files.walkFileTree(),完成目录的递归删除。具体实现为:通过FileVisitor实现类的visitFile()方法,逐个删除遍历目录中的文件,删除完目录包含的文件后,通过FileVisitor实现类的postVisitDirectory()方法删除目录本身。递归目录删除如下例:
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();
}
Files 类中的其他方法
java.nio,file.Files 类包含了很多有用的方法,如创建符号链接、确定文件大小、设置文件权限等。java.nio,file.Files详情可查阅javaDoc 。