【问题标题】:Why does Path.relativize behave differently on Java 8 and Java 11?为什么 Path.relativize 在 Java 8 和 Java 11 上的行为不同?
【发布时间】:2020-09-13 16:02:14
【问题描述】:

为什么relativize 方法在 上的行为不同?

Path path1 = Paths.get("/a/./b/../image.png");
Path path2 = Paths.get("/a/file.txt");
Path path = path1.relativize(path2);
System.out.println(path);
  • (准确地说是 1.8.0_66)打印 ../../../../file.txtJavaDoc
  • (准确地说是 11.0.4)打印 ../file.txtJavaDoc

两个版本的 JavaDoc 描述是相同的。我觉得 方式对我来说是正确的行为:

  • path1: /a/./b/../image.png 归一化为 /a/b/../image.png 归一化为 /a/image.png
  • path2: /a/file.txt
  • /a/image.png/a/file.txt导航的方式是../file.txt

问题

  1. 方式应该如何计算?它不会规范化路径吗?我不明白如何从head获取结果。

  2. 为什么这两个版本之间存在根本没有记录的差异?

【问题讨论】:

标签: java-8 java-11 java-8 java-11 java-11 java-8 java java-8 path java-11 nio2


【解决方案1】:

也许这个错误会回答你的问题: https://bugs.openjdk.java.net/browse/JDK-8066943

这影响了包含 .或 .. 并且已针对 Java 9 进行了修复。 所以这就是为什么你会看到 8 和 11 之间的差异。

【讨论】:

  • 有趣的是,这已在 2010 年被报告为 JDK-6925169,但显然从未修复(仅在 2018 年解决为“重复”)。
【解决方案2】:

此处提供基于 Windows 的源代码答案。

中的源代码观察(让我们看看sun.nio.fs.WindowsPathPath 的实现之一)与@987654322 相比具有额外的代码,包括规范化 @。

后一种实现的关键行从411行开始,所以基本上,后一种实现在计算相对路径之前规范化路径:

WindowsPath base = this;
if (base.hasDotOrDotDot() || child.hasDotOrDotDot()) {
    base = base.normalize();
    child = child.normalize();
}

进一步挖掘,jdk8-b120(源)和jdk-9+95(源)之间的实现变化。由于引入了模块化系统,两个类的实现和位置都不同:

  • Java 8 及以下版本:/jdk/src/windows/classes/sun/nio/fs/WindowsPath.java
  • Java 9 及以上版本:/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsPath.java

方式应该如何计算?它不会规范化路径吗?我不明白如何从head获取结果。

最直接的方法是先规范化两条路径,然后再将它们相对化。但我不知道它是否完全涵盖了所有java.nio.file.Path 实现并且这样做是否安全。

Path path = path1.normalize().relativize(path2.normalize());

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-10-27
    • 1970-01-01
    • 2015-02-25
    • 2016-10-31
    • 1970-01-01
    • 2021-05-25
    • 1970-01-01
    • 2013-08-30
    相关资源
    最近更新 更多