Java NIO系列教程(十四)Java NIO Path
Java NIO Path 接口是 Java 7 中引入的,用于表示文件系统中的路径。它支持创建绝对路径和相对路径,其中相对路径可使用
.和..来分别表示当前目录和父目录。Path 实例通过Paths.get()工厂方法创建。此外,Path 提供了relativize()方法来计算两个路径之间的相对关系,以及normalize()方法来消除路径中的冗余符号。它在功能上替代了传统的java.io.File类,提供了更现代的路径处理方式。
博主博客
Java Path 接口是 Java NIO 2 更新的一部分,该更新随 Java 6 和 Java 7 引入。Path 接口在 Java 7 中被添加到 Java NIO 中,位于 java.nio.file 包中,因此其完整限定名是 java.nio.file.Path。
Java Path 实例表示文件系统中的一个路径。该路径可以指向文件或目录,可以是绝对路径或相对路径。
- 绝对路径 包含从文件系统根目录到它所指向的文件或目录的完整路径。
- 相对路径 包含相对于某个其他路径到文件或目录的路径。相对路径可能听起来有些令人困惑,但请别担心,本教程后续会详细解释。
注意:请不要将文件系统路径与某些操作系统中的
PATH环境变量混淆。java.nio.file.Path接口与环境变量PATH无关。
在许多方面,java.nio.file.Path 接口类似于 java.io.File 类,但存在一些细微差别。不过,在许多情况下,您可以用 Path 接口来替代 File 类。
创建 Path 实例
要使用 java.nio.file.Path 实例,必须先创建它。您可以使用 Paths 类(java.nio.file.Paths)中的静态方法 Paths.get() 来创建 Path 实例。下面是一个示例:
import java.nio.file.Path;
import java.nio.file.Paths;
public class PathExample {
public static void main(String[] args) {
Path path = Paths.get("c:\\data\\myfile.txt");
}
}
注意示例顶部的两条 import 语句。要使用 Path 接口和 Paths 类,必须先导入它们。
其次,注意 Paths.get("c:\\data\\myfile.txt") 方法调用。正是对 Paths.get() 方法的调用创建了 Path 实例。换句话说,Paths.get() 方法是 Path 实例的工厂方法。
创建绝对路径
通过以绝对文件路径作为参数调用 Paths.get() 工厂方法来创建绝对路径。下面是一个创建表示绝对路径的 Path 实例的示例:
Path path = Paths.get("c:\\data\\myfile.txt");
绝对路径是 c:\data\myfile.txt。双反斜杠 \\ 在 Java 字符串中是必需的,因为 \ 是一个转义字符,意味着它后面的字符表示字符串中该位置实际的字符。通过写 \\,您告诉 Java 编译器在字符串中写入一个单独的 \ 字符。
上面的路径是一个 Windows 文件系统路径。在 Unix 系统(Linux、macOS、FreeBSD 等)上,上述绝对路径可能如下所示:
Path path = Paths.get("/home/jakobjenkov/myfile.txt");
此时的绝对路径是 /home/jakobjenkov/myfile.txt。
如果您在 Windows 机器上使用这种以 / 开头的路径,该路径将被解释为相对于当前驱动器。例如,路径 /home/jakobjenkov/myfile.txt 可能被解释为位于 C 盘,对应的完整路径将是:C:/home/jakobjenkov/myfile.txt。
创建相对路径
相对路径是从一个路径(基路径)指向目录或文件的路径。相对路径的完整路径(绝对路径)是通过将基路径与相对路径组合而得出的。
Java NIO Path 类也可用于处理相对路径。您可以使用 Paths.get(basePath, relativePath) 方法创建相对路径。以下是 Java 中两个相对路径的示例:
Path projects = Paths.get("d:\\data", "projects");
Path file = Paths.get("d:\\data", "projects\\a-project\\myfile.txt");
第一个示例创建了一个指向目录 d:\data\projects 的 Java Path 实例。
第二个示例创建了一个指向文件 d:\data\projects\a-project\myfile.txt 的 Path 实例。
处理相对路径时,可以在路径字符串中使用两种特殊代码:
.(当前目录)..(上级目录)
. 代码 表示“当前目录”。例如,如果您创建如下相对路径:
Path currentDir = Paths.get(".");System.out.println(currentDir.toAbsolutePath());
那么此 Java Path 实例对应的绝对路径将是执行上述代码的应用程序所在的目录。
如果 . 用在路径字符串的中间,它仅表示路径在那一刻所指向的同一目录。以下是一个说明这一点的 Path 示例:
Path currentDir = Paths.get("d:\\data\\projects\\.\\a-project");
此路径将对应于:d:\data\projects\a-project
.. 代码 表示“父目录”或“向上一级目录”。以下是一个说明这一点的 Java Path 示例:
Path parentDir = Paths.get("..");
此示例创建的 Path 实例将对应于运行此代码的应用程序启动目录的父目录。
如果您在路径字符串的中间使用 .. 代码,它将在该点对应于向上改变一级目录。例如:
String path = "d:\\data\\projects\\a-project\\..\\another-project";
Path parentDir2 = Paths.get(path);
此示例创建的 Java Path 实例将对应于以下绝对路径:
d:\data\projects\another-project
在 a-project 目录之后的 .. 代码将目录向上改变到父目录 projects,然后路径从那里向下引用到 another-project 目录。
. 和 .. 代码也可以与双字符串的 Paths.get() 方法结合使用。以下是两个展示简单用法的 Java Paths.get() 示例:
Path path1 = Paths.get("d:\\data\\projects", ".\\a-project");
Path path2 = Paths.get("d:\\data\\projects\\a-project", "..\\another-project");
Java NIO Path 类还有更多处理相对路径的方法,本教程后续会详细介绍。
relativize()
Java Path 的 relativize() 方法可以创建一个新的 Path,表示第二个 Path 相对于第一个 Path 的位置。例如,对于路径 /data 和 /data/subdata/subsubdata/myfile.txt,第二个路径可以表示为相对于第一个路径的 /subdata/subsubdata/myfile.txt。请看以下示例:
Path basePath = Paths.get("/data");
Path path = Paths.get("/data/subdata/subsubdata/myfile.txt");
Path basePathToPath = basePath.relativize(path);
Path pathToBasePath = path.relativize(basePath);
System.out.println(basePathToPath);
System.out.println(pathToBasePath);
此示例的输出将是:
subdata/subsubdata/myfile.txt
../../..
如果将相对路径 subdata/subsubdata/myfile.txt 添加到目录路径 /data,您将得到完整路径 /data/subdata/subsubdata/myfile.txt。
如果将相对路径 ../../.. 添加到完整文件路径 /data/subdata/subsubdata/myfile.txt,您将得到 /data。
注意:在尝试计算从一个 Path 到另一个 Path 的相对路径时,不能混合使用相对路径和绝对路径。
relativize()方法将抛出异常。因此,以下操作是不允许的:
Path basePath = Paths.get("/data");
Path path = Paths.get("myfile.txt");
Path basePathToPath = basePath.relativize(path);
如果尝试这样做,您将得到类似以下的异常:
Exception in thread "main" java.lang.IllegalArgumentException: 'other' is different type of Path
at java.base/sun.nio.fs.WindowsPath.relativize(WindowsPath.java:400)
at java.base/sun.nio.fs.WindowsPath.relativize(WindowsPath.java:42)
at com.jenkov.java.nio.PathExamples.main(PathExamples.java:33)
normalize()
Path 接口的 normalize() 方法可以规范化路径。规范化意味着它会移除路径字符串中间所有的 . 和 .. 代码,并解析路径字符串所引用的实际路径。以下是一个 Java Path.normalize() 的示例:
String originalPath = "d:\\data\\projects\\a-project\\..\\another-project";
Path path1 = Paths.get(originalPath);
System.out.println("path1 = " + path1);
Path path2 = path1.normalize();
System.out.println("path2 = " + path2);
此 Path 示例首先创建一个包含 .. 代码的路径字符串。然后,示例从此路径字符串创建一个 Path 实例并打印出来(实际上是打印 Path.toString())。
接着,示例在创建的 Path 实例上调用 normalize(),该方法返回一个新的 Path 实例。这个新的、规范化的 Path 实例随后也被打印出来。
以下是上述示例的输出:
path1 = d:\data\projects\a-project\..\another-project
path2 = d:\data\projects\another-project
如您所见,规范化后的路径不包含 a-project\.. 部分,因为这是冗余的。被移除的部分并未对最终的绝对路径添加任何信息。
参考文献
Java NIO系列教程(十四)Java NIO Path
https://blog.uso6.com/archives/java-nioxi-lie-jiao-cheng-shi-si-java-nio-path
评论