创建和阅读目录

先前讨论的某些方法(例如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的对象。实现DirectoryStreaminterface的类也实现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);
}

此方法仅用于过滤单个目录。但是,如果要在文件树中找到所有子目录,则可以对走文件树使用该机制。