了解java.nio.file.Path.relativize(Path other)

Luc*_*s T 6 java java-8

我试图熟悉java.nio.file.Path.relativize()无济于事.

我已经阅读了javadocs,我看过了一些例子.但是,我仍然无法理解以下示例(我使用Linux,向窗口用户道歉):

程序的工作目录是:/ home/userspace/workspace/java8.

有两个文件:/home/userspace/workspace/java8/zoo.txt和/home/userspace/temp/delete/dictionary.txt

以下程序调用Path.relativize():

package certExam.java8.ch9NIO.paths;
import java.nio.file.Path;
import java.nio.file.Paths;
public class Relativize 
{
    public static void main(String[] args) 
    {
        Path relativePathToZoo = Paths.get("zoo.txt");
        Path relativePathToDictionary = Paths.get("../../temp/delete/dictionary.txt");
        System.out.println("relativePathToZoo.relativize(relativePathToDictionary): "+relativePathToZoo.relativize(relativePathToDictionary));
        System.out.println("relativePathToZoo.relativize(relativePathToDictionary).toAbsolutePath(): "+relativePathToZoo.relativize(relativePathToDictionary).toAbsolutePath());
        System.out.println("relativePathToZoo.relativize(relativePathToDictionary).toAbsolutePath().normalize(): "+relativePathToZoo.relativize(relativePathToDictionary).toAbsolutePath().normalize());
        System.out.println("relativePathToDictionary.relativize(relativePathToZoo): "+relativePathToDictionary.relativize(relativePathToZoo));
        System.out.println("relativePathToDictionary.relativize(relativePathToZoo).toAbsolutePath().normalize(): "+relativePathToDictionary.relativize(relativePathToZoo).toAbsolutePath().normalize());
        System.out.println();
    }
}
Run Code Online (Sandbox Code Playgroud)

输出是:

relativePathToZoo.relativize(relativePathToDictionary): ../../../temp/delete/dictionary.txt 
    relativePathToZoo.relativize(relativePathToDictionary).toAbsolutePath(): /home/userspace/workspace/java8/../../../temp/delete/dictionary.txt 
    relativePathToZoo.relativize(relativePathToDictionary).toAbsolutePath().normalize(): /home/temp/delete/dictionary.txt 
    relativePathToDictionary.relativize(relativePathToZoo): ../../../../../zoo.txt 
    relativePathToDictionary.relativize(relativePathToZoo).toAbsolutePath().normalize(): /zoo.txt
Run Code Online (Sandbox Code Playgroud)

我的问题,我无法理解的是:为什么relativePathToDictionary.relativize(relativePathToZoo)输出../../../../../zoo.txt?

规范化后,它会让你认为zoo.txt存在于根目录中.

relativize()如何解决这样一条深刻的道路?我知道relativize()与当前工作目录相关,因此它会向每个路径添加.. 但是我无法理解,它如何解决了与fonts.txt相关的zoo.txt的路径.

提前致谢,

卢卡斯

Hol*_*ger 14

首先,当前的工作目录完全无关紧要.我甚至可以在Windows下重现你的问题,我的系统上没有任何这些文件和目录,唯一的区别是使用\\而不是/.

该怎么relativize办?如果你有这样的路径foo bar baz,并要求相对化foo bar hello,你会得到.. hello的是这样的路径,相对于foo bar bazfoo bar hello,即Paths.get("foo", "bar", "baz").resolve(Paths.get("..", "hello")).normalize()产生相同的路径Paths.get("foo", "bar", "hello"),无论任何真正的文件系统结构.

现在你遇到了一个错误JDK-6925169,正如用户Berger在评论中所建议的那样.该Path实现不能正确处理...组件relativize,但将它们视为任何其他路径组件.

因此,无论您使用Paths.get("..", "..", "temp", "delete", "dictionary.txt")or Paths.get("a", "b", "c", "d", "e"),它都没有区别,在任何一种情况下,实现都会将其视为五个不匹配的路径组件,必须将其删除才能解析Paths.get("zoo.txt").这适用于Windows和Linux.您可以使用以下与平台无关的代码进行验证:

Path relative = Paths.get("zoo.txt");
Path base1 = Paths.get("..", "..", "temp", "delete", "dictionary.txt");
Path base2 = Paths.get("a",  "b",  "c",    "d",      "e");

Path relativized1 = base1.relativize(relative);
System.out.println("relativized1: "+relativized1);
Path relativized2 = base2.relativize(relative);
System.out.println("relativized2: "+relativized2);

Path resolved1 = base1.resolve(relativized1).normalize();
System.out.println("resolved1="+resolved1);
Path resolved2 = base2.resolve(relativized2).normalize();
System.out.println("resolved2="+resolved2);
Run Code Online (Sandbox Code Playgroud)

由于relatize错误地将所有组件视为相同,因此相对化路径是相同的,但由于normalize操作确实处理..路径组件,因此第一个已解决的路径将显示问题,而第二个解析为预期的路径zoo.txt.

理解这一点可能很重要,所有路径组件(包括dictionary.txt)都被视为目录.文档relativize没有明确提及,但您可以从记录的关系中得出它resolve,其文档说" ......此方法将此路径视为目录 ".


Zac*_*des 12

在这个例子中,我们想从zoo.txt到elephant.bin.那么让我们从zoo.txt开始,问问自己如何从zoo.txt到elephant.bin.首先,我必须上一个目录,所以我使用".."现在我在临时.如果它有帮助,用手指跟踪步骤!我必须再向java上去,所以我再次使用"..".现在我在java.文件箱在java中,所以我使用"/ bin"进入它.我再一次使用"/elephant.bin".我们到达了目的地.

Path p1 = Paths.get("java/temp/zoo.txt");
Path p2 = Paths.get("java/bin/elephant.bin");

Path p1Top2 = p1.relativize(p2);
System.out.println(p1Top2); 
Run Code Online (Sandbox Code Playgroud)

将我们采取的所有上述步骤放在一起,您就可以获得输出

../../bin/elephant.bin
Run Code Online (Sandbox Code Playgroud)

  • 谢谢你的例子。我认为 `p1.relativize(p2)` 返回 `p1` 的相对路径会更合乎逻辑,但...... (2认同)