【问题标题】:Understanding java.nio.file.Path.relativize(Path other)理解 java.nio.file.Path.relativize(Path other)
【发布时间】:2016-10-11 09:37:57
【问题描述】:

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

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

程序的工作目录是:/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();
    }
}

输出是:

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

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

当归一化时,它会让你认为 zoo.txt 存在于根目录中。

relativize() 是如何得出这么深的路径的?我知道 relativize() 与当前工作目录相关,因此它会将 .. 添加到每个路径。但我无法理解,它是如何计算出与 dictionary.txt 相关的 zoo.txt 路径。

【问题讨论】:

  • 记住relativize返回的东西可以传递给resolve,resolve assumes its Path represents a directory.因此,relativize也假设它的Path是一个目录。
  • 经过一段时间的思考,我明白了这一点:我正在终端上的目录上导航,我想用一个 cd 命令从路径 A 转到路径 B。这就是 relativize 的输出

标签: java java-8


【解决方案1】:

鉴于以下示例路径:

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); 

在此示例中,我们希望从 zoo.txtelephant.bin。 所以,让我们从zoo.txt 开始,问问自己:我如何从zoo.txtelephant.bin。首先我必须上一个目录,所以我使用“..”现在我在temp。 (如果有帮助,请用手指跟踪步骤!)。我必须再上一级到java,所以我再次使用“..”。现在我在java。目录binjava 中,所以,我使用“/bin”来访问它。我再一次使用“/elephant.bin”。我们已经到达目的地了。

将我们采取的所有上述步骤放在一起,您就会得到输出:

../../bin/elephant.bin

【讨论】:

  • 感谢您的示例。我认为p1.relativize(p2) 返回p1 的相对路径会更合乎逻辑,不过...
  • 这个解释真是开窍了啊哈!我的时刻。这几天我一直在为此苦苦挣扎!谢谢!
【解决方案2】:

首先,当前工作目录是完全不相关的。即使在 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") 还是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);

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

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

【讨论】:

    猜你喜欢
    • 2014-01-20
    • 1970-01-01
    • 2017-10-11
    • 1970-01-01
    • 2012-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-24
    相关资源
    最近更新 更多