Java NIO files
Java NIO files
java.nio.file.Files
类提供了许多操作文件的方法,它们往往和Path类合作使用。
1.Files.exits()
Files#exits()
方法检查一个Path是否存在于当前的文件系统中。假如我们直接使用Path实例的相关方法,那么一个不存在的文件可能会被创建,如果我们想避免这种情况的发生,那么可以先使用Files#extis()
来进行一下检查。
Path path = Paths.get("data/logging.properties");
boolean pathExists =
Files.exists(path,
new LinkOption[]({LinkOption.NOFOLLOW_LINKS});
显然,exits()
方法有两个参数,第一个是要检查的path,第二个是exits()
方法的选项数组。如LinkOption.NOFOLLOW_LINKS
代表不允许跟随文件系统中的符号链接来确定路径是否存在。
2.Files.createDirectory()
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();
}
通过上面的示例一眼就可以看出这个方法是干嘛用的,另外就是注意一下通过抛出异常来对不同的情况进行处理。
注:假如父目录不存在,可能抛出IOException
异常。
3.Files.copy()
Files#copy()
方法将文件从一个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();
}
功能太明显了。如果目标文件已存在,会抛出FileAlreadyExistsException
,如果试图将文件复制到不存在的目录,会抛出IOException
。
但也可以要求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();
}
在copy方法的参数列表中加上这个StandardCopyOption.REPLACE_EXISTING
,可以在目标文件存在时强制覆盖。
4.FIles.move()
Files#move()
方法将文件从一个path移动到另一个path。同时可以设定目标的文件名,也就是说不仅可以实现移动功能,也可以实现重命名或移动+重命名。
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();
}
功能显而易见,StandardCopyOption.REPLACE_EXISTING
参数的意义和copy
方法中的一样。
5.Files.delete()
Files#delete()
方法可以删除一个文件或文件夹。
Path path = Paths.get("data/subdir/logging-moved.properties");
try {
Files.delete(path);
} catch (IOException e) {
//deleting file failed
e.printStackTrace();
}
6.Files.walkFileTree()
Files.walkFileTree()
方法可以递归遍历目录树。它使用一个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 {
}
Files.walkFileTree()
方法需要一个FileVisitor
的实现类作为参数,实现FileVisitor
接口就需要实现上述方法。如果不想做特殊实现或者只想实现一部分,可以继承SimpleFileVisitor
类,它其中有对FileVisitor
的方法的默认实现。
下面是示例:
Files.walkFileTree(path, new FileVisitor<Path>() {
@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
枚举,这些返回指决定了遍历如何进行。包括
-
CONTINUE
。表示遍历将继续正常进行。 -
TERMINATE
。表示文件遍历将终止。 -
SKIP_SIBLINGS
。表示文件遍历将继续,但不在访问此文件/目录的同级文件/目录。 -
SKIP_SUBTREE
。表示文件遍历将继续,但不再访问此目录内的文件。
下面是一个通过walkFileTree()
方法寻找名字为README.txt
的文件的示例。注意这里的FileVisitor
是继承SimpleFileVisitor
的,不过重写了visitFile
方法。
Path rootPath = Paths.get("data");
String fileToFind = File.separator + "README.txt";
try {
Files.walkFileTree(rootPath, new SimpleFileVisitor<Path>() {
@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();
}
下面是一个通过walkFileTree()
方法删除名字为README.txt
的文件的示例。注意这里的FileVisitor
是继承SimpleFileVisitor
的,不过重写了visitFile
方法和postVisitDirectory
方法。
Files#delete()
方法仅在目录为空时删除目录,但下面的代码可以递归删除。
Path rootPath = Paths.get("data/to-delete");
try {
Files.walkFileTree(rootPath, new SimpleFileVisitor<Path>() {
@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();
}
7.其他方法
Files类中还有许多其他方法,可以自己去看API。