创建和阅读目录
先前讨论的某些方法(例如delete
)可处理文件,链接和目录。但是,如何在文件系统的顶部列出所有目录?如何列出目录的内容或创建目录?
本节涵盖以下特定于目录的功能:
列出文件系统的根目录
您可以使用FileSystem.getRootDirectories方法列出文件系统的所有根目录。此方法返回Iterable
,使您可以使用enhanced for语句遍历所有根目录。
以下代码片段将打印默认文件系统的根目录:
Iterable<Path> dirs = FileSystems.getDefault().getRootDirectories();
for (Path name: dirs) {
System.err.println(name);
}
创建目录
您可以使用createDirectory(Path, FileAttribute<?>)方法创建一个新目录。如果您未指定任何FileAttributes
,则新目录将具有默认属性。例如:
Path dir = ...;
Files.createDirectory(path);
以下代码段在具有特定权限的 POSIX 文件系统上创建一个新目录:
Set<PosixFilePermission> perms =
PosixFilePermissions.fromString("rwxr-x---");
FileAttribute<Set<PosixFilePermission>> attr =
PosixFilePermissions.asFileAttribute(perms);
Files.createDirectory(file, attr);
要在一个或多个父目录可能不存在的情况下创建几个级别的目录,可以使用便捷方法createDirectories(Path, FileAttribute<?>)。与createDirectory(Path, FileAttribute<?>)
方法一样,您可以指定一组可选的初始文件属性。以下代码段使用默认属性:
Files.createDirectories(Paths.get("foo/bar/test"));
根据需要,从上至下创建目录。在foo/bar/test
示例中,如果foo
目录不存在,则会创建该目录。接下来,根据需要创建bar
目录,最后创建test
目录。
创建一些而非全部父目录后,此方法可能会失败。
创建临时目录
您可以使用createTempDirectory
方法之一创建临时目录:
第一种方法允许代码为临时目录指定位置,第二种方法在默认的临时文件目录中创建一个新目录。
列出目录的内容
您可以使用newDirectoryStream(Path)方法列出目录的所有内容。此方法返回一个实现DirectoryStreaminterface的对象。实现DirectoryStream
interface的类也实现Iterable
,因此您可以遍历目录流,读取所有对象。这种方法可以很好地扩展到非常大的目录。
Remember:
返回的DirectoryStream
是* stream *。如果您不使用try-
with-resources 语句,请不要忘记关闭finally
块中的流。 try-
with-resources 语句为您解决了这一问题。
以下代码段显示了如何打印目录的内容:
Path dir = ...;
try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
for (Path file: stream) {
System.out.println(file.getFileName());
}
} catch (IOException | DirectoryIteratorException x) {
// IOException can never be thrown by the iteration.
// In this snippet, it can only be thrown by newDirectoryStream.
System.err.println(x);
}
迭代器返回的Path
对象是针对目录解析的条 Object 名称。因此,如果要列出/tmp
目录的内容,则将以/tmp/a
,/tmp/b
的形式返回条目,依此类推。
此方法返回目录的全部内容:文件,链接,子目录和隐藏文件。如果要对检索到的内容有更多选择,可以使用其他newDirectoryStream
方法之一,如本页面稍后所述。
请注意,如果在目录迭代期间发生异常,则引发DirectoryIteratorException
并引发IOException
作为原因。迭代器方法不能引发异常异常。
使用 globbing 过滤目录列表
如果只想获取每个名称都与特定 Pattern 匹配的文件和子目录,则可以使用newDirectoryStream(Path, String)方法来完成,该方法提供了内置的全局过滤器。如果您不熟悉 glob 语法,请参见什么是地球仪?
例如,以下代码段列出了与 Java 相关的文件:* .class , .java 和 .jar *文件。:
Path dir = ...;
try (DirectoryStream<Path> stream =
Files.newDirectoryStream(dir, "*.{java,class,jar}")) {
for (Path entry: stream) {
System.out.println(entry.getFileName());
}
} catch (IOException x) {
// IOException can never be thrown by the iteration.
// In this snippet, it can // only be thrown by newDirectoryStream.
System.err.println(x);
}
编写自己的目录过滤器
也许您想基于 Pattern 匹配以外的其他条件来过滤目录的内容。您可以通过实现DirectoryStream.Filter<T>interface来创建自己的过滤器。此interface包含一种方法accept
,该方法确定文件是否满足搜索要求。
例如,以下代码片段实现了仅检索目录的过滤器:
DirectoryStream.Filter<Path> filter =
newDirectoryStream.Filter<Path>() {
public boolean accept(Path file) throws IOException {
try {
return (Files.isDirectory(path));
} catch (IOException x) {
// Failed to determine if it's a directory.
System.err.println(x);
return false;
}
}
};
一旦创建了过滤器,就可以使用newDirectoryStream(Path,DirectoryStream.Filter<? super Path>)方法来调用它。以下代码段使用isDirectory
过滤器仅将目录的子目录打印到标准输出:
Path dir = ...;
try (DirectoryStream<Path>
stream = Files.newDirectoryStream(dir, filter)) {
for (Path entry: stream) {
System.out.println(entry.getFileName());
}
} catch (IOException x) {
System.err.println(x);
}
此方法仅用于过滤单个目录。但是,如果要在文件树中找到所有子目录,则可以对走文件树使用该机制。