# 创建和阅读目录

> 原文： [https://docs.oracle.com/javase/tutorial/essential/io/dirs.html](https://docs.oracle.com/javase/tutorial/essential/io/dirs.html)

前面讨论过的一些方法，如`delete`，适用于文件，链接 _ 和 _ 目录。但是如何列出文件系统顶部的所有目录？如何列出目录的内容或创建目录？

本节介绍以下特定于目录的功能：

*   [列出文件系统的根目录](#listall)
*   [创建目录](#create)
*   [创建临时目录](#createTemp)
*   [列出目录的内容](#listdir)
*   [使用 Globbing](#glob) 过滤目录列表
*   [编写自己的目录过滤器](#filter)

您可以使用 [`FileSystem.getRootDirectories`](https://docs.oracle.com/javase/8/docs/api/java/nio/file/FileSystem.html#getRootDirectories--) 方法列出文件系统的所有根目录。此方法返回`Iterable`，使您可以使用增强的语句迭代所有根目录。

以下代码段打印默认文件系统的根目录：

```
Iterable<Path> dirs = FileSystems.getDefault().getRootDirectories();
for (Path name: dirs) {
    System.err.println(name);
}

```

您可以使用 [`createDirectory(Path, FileAttribute&lt;?&gt;)`](https://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#createDirectory-java.nio.file.Path-java.nio.file.attribute.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&lt;?&gt;)`](https://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#createDirectories-java.nio.file.Path-java.nio.file.attribute.FileAttribute...-) 。与`createDirectory(Path, FileAttribute&lt;?&gt;)`方法一样，您可以指定一组可选的初始文件属性。以下代码段使用默认属性：

```
Files.createDirectories(Paths.get("foo/bar/test"));

```

根据需要，从上到下创建目录。在`foo/bar/test`示例中，如果`foo`目录不存在，则创建它。接下来，如果需要，创建`bar`目录，最后创建`test`目录。

创建一些（但不是全部）父目录后，此方法可能会失败。

您可以使用`createTempDirectory`方法之一创建临时目录：

*   [`createTempDirectory(Path, String, FileAttribute&lt;?&gt;...)`](https://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#createTempDirectory-java.nio.file.Path-java.lang.String-java.nio.file.attribute.FileAttribute...-)
*   [`createTempDirectory(String, FileAttribute&lt;?&gt;...)`](https://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#createTempDirectory-java.lang.String-java.nio.file.attribute.FileAttribute...-)

第一种方法允许代码指定临时目录的位置，第二种方法在默认的 temporary-fle 目录中创建新目录。

您可以使用 [`newDirectoryStream(Path)`](https://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#newDirectoryStream-java.nio.file.Path-) 方法列出目录的所有内容。此方法返回实现 [`DirectoryStream`](https://docs.oracle.com/javase/8/docs/api/java/nio/file/DirectoryStream.html) 接口的对象。实现`DirectoryStream`接口的类也实现了`Iterable`，因此您可以遍历目录流，读取所有对象。这种方法适用于非常大的目录。

* * *

**Remember:** The returned `DirectoryStream` is a _stream_. If you are not using a `try-`with-resources statement, don't forget to close the stream in the `finally` block. The `try-`with-resources statement takes care of this for you.

* * *

以下代码段显示了如何打印目录的内容：

```
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`对象是针对目录解析的条目的名称。因此，如果列出`/tmp`目录的内容，则以`/tmp/a`，`/tmp/b`等形式返回条目。

此方法返回目录的全部内容：文件，链接，子目录和隐藏文件。如果您希望对检索的内容更具选择性，可以使用其他`newDirectoryStream`方法之一，如本页后面所述。

请注意，如果在目录迭代期间存在异常，则抛出`DirectoryIteratorException`并将`IOException`作为原因。迭代器方法不能抛出异常异常。

##  过滤目录列表

如果只想获取每个名称与特定模式匹配的文件和子目录，可以使用 [`newDirectoryStream(Path, String)`](https://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#newDirectoryStream-java.nio.file.Path-java.lang.String-) 方法，它提供内置的全局过滤器。如果您不熟悉 glob 语法，请参阅[什么是全局？](fileOps.html#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);
}

```

您可能希望根据模式匹配以外的某些条件过滤目录的内容。您可以通过实现 [`DirectoryStream.Filter&lt;T&gt;`](https://docs.oracle.com/javase/8/docs/api/java/nio/file/DirectoryStream.Filter.html) 接口来创建自己的过滤器。该接口由一个方法`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&lt;? super Path&gt;)`](https://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#newDirectoryStream-java.nio.file.Path-java.nio.file.DirectoryStream.Filter-) 方法调用它。以下代码段使用`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);
}

```

此方法仅用于过滤单个目录。但是，如果要查找文件树中的所有子目录，可以使用[走动文件树](walk.html)的机制。