Path Operations

Path类包括各种方法,可用于获取有关路径的信息,访问路径的元素,将路径转换为其他形式或提取路径的一部分。还有匹配路径字符串 的方法和消除路径冗余的方法。本类介绍了这些Path方法(有时称为* syntactic *操作),因为它们在路径本身上进行操作并且不访问文件系统。

本节包括以下内容:

创建路径

Path实例包含用于指定文件或目录位置的信息。在定义时,为Path提供了一系列一个或多个名称。可能包含根元素或文件名,但都不是必需的。 Path可能只包含一个目录或文件名。

您可以使用Paths(请注意复数)帮助器类中的以下get方法之一来轻松创建Path对象:

Path p1 = Paths.get("/tmp/foo");
Path p2 = Paths.get(args[0]);
Path p3 = Paths.get(URI.create("file:///Users/joe/FileTest.java"));

Paths.get方法是以下代码的简写:

Path p4 = FileSystems.getDefault().getPath("/users/sally");

下面的示例假设您的主目录为/u/joe,或者如果为 Windows,则为C:\joe\logs\foo.log来创建/u/joe/logs/foo.log

Path p5 = Paths.get(System.getProperty("user.home"),"logs", "foo.log");

检索有关路径的信息

您可以将Path视为将这些名称元素存储为序列。目录结构中的最高元素将位于索引 0.目录结构中的最低元素将位于索引[n-1],其中nPath中名称元素的数量。可使用方法使用这些索引来检索单个元素或Path的子序列。

本课中的示例使用以下目录结构。

samples 目录结构

samples 目录结构

以下代码段定义一个Path实例,然后调用几种方法来获取有关路径的信息:

// None of these methods requires that the file corresponding
// to the Path exists.
// Microsoft Windows syntax
Path path = Paths.get("C:\\home\\joe\\foo");

// Solaris syntax
Path path = Paths.get("/home/joe/foo");

System.out.format("toString: %s%n", path.toString());
System.out.format("getFileName: %s%n", path.getFileName());
System.out.format("getName(0): %s%n", path.getName(0));
System.out.format("getNameCount: %d%n", path.getNameCount());
System.out.format("subpath(0,2): %s%n", path.subpath(0,2));
System.out.format("getParent: %s%n", path.getParent());
System.out.format("getRoot: %s%n", path.getRoot());

这是 Windows 和 Solaris OS 的输出:

Method Invoked在 Solaris OS 中返回在 Microsoft Windows 中返回Comment
toString/home/joe/fooC:\home\joe\foo返回Path的字符串 表示形式。如果路径是使用Filesystems.getDefault().getPath(String)Paths.get创建的(后者是getPath的便捷方法),则该方法将执行较小的语法清除。例如,在 UNIXos 中,它将把 Importing 字符串//home/joe/foo纠正为/home/joe/foo
getFileNamefoofoo返回文件名或名称元素序列的最后一个元素。
getName(0)homehome返回与指定索引对应的路径元素。第 0 个元素是最接近根的路径元素。
getNameCount33返回路径中的元素数。
subpath(0,2)home/joehome\joe返回由开始和结束索引指定的Path的子序列(不包括根元素)。
getParent/home/joe\home\joe返回父目录的路径。
getRoot/C:\返回路径的根。

前面的示例显示了绝对路径的输出。在以下示例中,指定了相对路径:

// Solaris syntax
Path path = Paths.get("sally/bar");
or
// Microsoft Windows syntax
Path path = Paths.get("sally\\bar");

这是 Windows 和 Solaris OS 的输出:

Method Invoked在 Solaris OS 中返回在 Microsoft Windows 中返回
toStringsally/barsally\bar
getFileNamebarbar
getName(0)sallysally
getNameCount22
subpath(0,1)sallysally
getParentsallysally
getRootnullnull

从路径中删除冗余

许多文件系统使用“。”符号表示当前目录,“ ..”表示父目录。您可能遇到了Path包含冗余目录信息的情况。也许将服务器配置为将其日志文件保存在“ /dir/logs/.”目录中,并且您要从路径中删除尾随的“ /.”表示法。

以下示例均包括冗余:

/home/./joe/foo
/home/sally/../joe/foo

normalize方法删除所有冗余元素,其中包括任何出现的“ .”或“ directory/..”。前面的两个示例均标准化为/home/joe/foo

重要的是要注意normalize在清理路径时不会检查文件系统。这是纯语法操作。在第二个示例中,如果sally是符号链接,则删除sally/..可能会导致Path不再定位目标文件。

要在确保结果找到正确文件的同时清理路径,可以使用toRealPath方法。下一部分转换路径中将描述此方法。

转换路径

您可以使用三种方法来转换Path。如果需要将路径转换为可以从浏览器打开的字符串,则可以使用toUri。例如:

Path p1 = Paths.get("/home/logfile");
// Result is file:///home/logfile
System.out.format("%s%n", p1.toUri());

toAbsolutePath方法将路径转换为绝对路径。如果传入的路径已经是绝对路径,则它将返回相同的Path对象。 toAbsolutePath方法在处理用户 Importing 的文件名时非常有用。例如:

public class FileTest {
    public static void main(String[] args) {

        if (args.length < 1) {
            System.out.println("usage: FileTest file");
            System.exit(-1);
        }

        // Converts the input string to a Path object.
        Path inputPath = Paths.get(args[0]);

        // Converts the input Path
        // to an absolute path.
        // Generally, this means prepending
        // the current working
        // directory.  If this example
        // were called like this:
        //     java FileTest foo
        // the getRoot and getParent methods
        // would return null
        // on the original "inputPath"
        // instance.  Invoking getRoot and
        // getParent on the "fullPath"
        // instance returns expected values.
        Path fullPath = inputPath.toAbsolutePath();
    }
}

toAbsolutePath方法转换用户 Importing,并返回Path,该Path在查询时返回有用的值。该文件不需要存在就可以使用此方法。

toRealPath方法返回现有文件的* real *路径。此方法一次执行多项操作:

  • 如果将true传递给此方法,并且文件系统支持符号链接,则此方法将解析路径中的所有符号链接。

  • 如果Path是相对的,则返回绝对路径。

  • 如果Path包含任何冗余元素,它将返回删除了那些元素的路径。

如果文件不存在或无法访问,则此方法将引发异常。当您要处理任何一种情况时,都可以catch异常。例如:

try {
    Path fp = path.toRealPath();
} catch (NoSuchFileException x) {
    System.err.format("%s: no such" + " file or directory%n", path);
    // Logic for case when file doesn't exist.
} catch (IOException x) {
    System.err.format("%s%n", x);
    // Logic for other sort of file error.
}

结合两条道路

您可以使用resolve方法合并路径。您传入* partial path *,这是不包含根元素的路径,并且该部分路径被追加到原始路径。

例如,考虑以下代码片段:

// Solaris
Path p1 = Paths.get("/home/joe/foo");
// Result is /home/joe/foo/bar
System.out.format("%s%n", p1.resolve("bar"));

or

// Microsoft Windows
Path p1 = Paths.get("C:\\home\\joe\\foo");
// Result is C:\home\joe\foo\bar
System.out.format("%s%n", p1.resolve("bar"));

将绝对路径传递给resolve方法将返回传入的路径:

// Result is /home/joe
Paths.get("foo").resolve("/home/joe");

在两条路径之间创建一条路径

编写文件 I/O 代码时,常见的要求是能够构造从文件系统中一个位置到另一位置的路径。您可以使用relativize方法来实现。此方法构造一条路径,该路径从原始路径开始,并终止于传入路径指定的位置。新路径相对于原始路径是“相对”的。

例如,考虑定义为joesally的两个相对路径:

Path p1 = Paths.get("joe");
Path p2 = Paths.get("sally");

在没有其他任何信息的情况下,假定joesally是同级,即节点位于树结构中的同一级别。要从joe导航到sally,您应该希望先向上导航到父节点然后再向下导航到sally

// Result is ../sally
Path p1_to_p2 = p1.relativize(p2);
// Result is ../joe
Path p2_to_p1 = p2.relativize(p1);

考虑一个稍微复杂的示例:

Path p1 = Paths.get("home");
Path p3 = Paths.get("home/sally/bar");
// Result is sally/bar
Path p1_to_p3 = p1.relativize(p3);
// Result is ../..
Path p3_to_p1 = p3.relativize(p1);

在此示例中,两条路径共享相同的节点home。要从home导航到bar,请先将一个级别向下导航到sally,然后再向下一个级别导航至bar。从barhome导航需要上移两个级别。

如果只有一个路径包含根元素,则无法构造相对路径。如果两个路径都包含根元素,则构造相对路径的能力取决于系统。

递归Copy示例使用relativizeresolve方法。

比较两条路径

Path类支持equals,使您能够测试两条路径的相等性。 startsWithendsWith方法使您能够测试路径是以特定字符串 开头还是结尾。这些方法易于使用。例如:

Path path = ...;
Path otherPath = ...;
Path beginning = Paths.get("/home");
Path ending = Paths.get("foo");

if (path.equals(otherPath)) {
    // equality logic here
} else if (path.startsWith(beginning)) {
    // path begins with "/home"
} else if (path.endsWith(ending)) {
    // path ends with "foo"
}

Path类实现Iterableinterface。 iterator方法返回一个对象,该对象使您可以遍历路径中的名称元素。返回的第一个元素是最接近目录树根目录的元素。以下代码段遍历路径,打印每个 name 元素:

Path path = ...;
for (Path name: path) {
    System.out.println(name);
}

Path类还实现Comparableinterface。您可以使用compareTo来比较Path个对象,这对排序很有用。

您还可以将Path个对象放入Collection。有关此强大功能的更多信息,请参见Collections

当您要验证两个Path对象位于同一文件中时,可以使用isSameFile方法,如检查两个路径是否找到相同的文件中所述。