【问题标题】:Is this a bug in java jdk?这是java jdk中的错误吗?
【发布时间】:2016-07-12 19:00:09
【问题描述】:

当我得到一个代码为File file = new File("e:/"); 的java.lang.File 类时,当然我得到了一个代表e:\ 目录的File 类。

但是,如果我得到一个代码为File file = new File("e:"); 的文件类并且我只是在驱动器 E: 中,那么我得到一个代表当前目录的文件类。

假设我在目录 E:\dir\,并且这个目录有一个名为 Test.java 的文件。 它的内容是:

import java.io.File;
public class Test {
    public static void main(String[] args) {
        File file = new File("e:"); 
        File[] files = file.listFiles(); 
        for(File f: files){ 
            System.out.println(f + " " + f.exists()); 
        }
    }
}

打开cmd工具,导航到目录e:\dir,在里面执行如下命令:

E:\dir> javac Test.java
E:\dir> java Test

我明白了:

e:\Test.class false
e:\Test.java false

这是一个 java jdk 错误吗?


来自@JimGarrison 的其他信息:

我运行了这段代码

public class Foo3
{
    public static void main(String[] args)  throws Exception
    {
        File f = new File("D:");
        System.out.println(f.getCanonicalPath());
        for (File x : f.listFiles())
            System.out.println(x + " " + x.getCanonicalPath() + " " + x.getAbsolutePath() + " " + x.exists() + " " + x.getAbsoluteFile().exists());
    }
}

在 Eclipse(位于我的 D: 驱动器上)并得到以下输出:

D:\dev\src\pdxep
D:\.classpath D:\dev\src\pdxep\.classpath D:\dev\src\pdxep\.classpath false true
D:\.project D:\dev\src\pdxep\.project D:\dev\src\pdxep\.project false true
D:\.settings D:\dev\src\pdxep\.settings D:\dev\src\pdxep\.settings false true
D:\gallery D:\dev\src\pdxep\gallery D:\dev\src\pdxep\gallery false true
D:\pom.xml D:\dev\src\pdxep\pom.xml D:\dev\src\pdxep\pom.xml false true
D:\src D:\dev\src\pdxep\src D:\dev\src\pdxep\src false true
D:\target D:\dev\src\pdxep\target D:\dev\src\pdxep\target false true

这证实了一些有趣的事情正在发生。

Java Bug 8130462 似乎与 Windows 中的相对路径和绝对路径有关。

【问题讨论】:

  • 很好奇。我也可以重现这个问题。
  • 我运行了上面写的程序(尽管我将类名修改为 TestFile),并收到了 e: 驱动器(Windows 10)的预期输出(列出的文件和目录等)。运行 Java 1.8.0_72。 @JimGarrison 很有趣你重现了这个问题。从 Eclipse 和命令行运行它。唯一的区别是我有一个包名,所以它是 java -cp ./bin package.TestFile
  • 如果您在调试器中运行并在println 处停止,您可以看到路径和规范路径之间存在差异。您看到的输出(缺少当前目录)似乎是用于查找文件的内容,但打印规范路径包括当前目录。当然看起来像一个错误(可能在 Windows 文件系统提供程序的实现中)。从显式完整路径字符串创建文件没有这个问题。
  • @KevinO 也许您是从根目录运行而不是从根目录运行的文件夹?我也可以复制——非常奇怪。我同意这是 FileSystem 中的一个问题,因为 File c'tor 中的第一行是 this.path = fs.normalize(pathname); 其中 fs 是 FileSystem跨度>
  • 我已经用更多信息更新了这个问题。由于File 中至少有一个长期存在的错误与绝对路径与相对路径有关,我怀疑这是另一个(或现有错误的结果,在我对问题的更新中链接)。

标签: java windows file


【解决方案1】:

关于获取File 代表当前工作目录和代码File file = new File("e:"); 的第一部分不是错误。它是一个 Windows“驱动器相对路径”。即,相对于指定驱动器中当前工作目录的路径。 (是的,Windows 每个驱动器都有不同的工作导向器)

问题是 Java 在路径中的驱动器号之后错误地添加了 \,这使得路径看起来像绝对路径,并在 file.exists() 上错误地返回 false 可能是因为这个原因。

但是,Java 正确解析规范路径和绝对路径,并在 x.getAbsoluteFile().exists() 上正确返回 true。正如您在示例代码中注意到的那样,Java 还正确地返回了 file.listFiles() 中的 CWD 的内容。

我在JDK-5066567 的数据库中发现了一个旧错误,或者至少与此非常相似。它创建于 2004 年,并在 2013 年设置为“进行中”,当前的受让人处于“非活动状态”,所以我认为我们不会很快看到任何解决方案,如果有的话。

所以要回答你的问题,我会说是的,这是一个错误。

不过,在java.nio.file.Path 中似乎处理得更好。因此,如果可以在您的用例中改用 java.nio.file.* 包,这可能是一个可以接受的解决方法。

【讨论】:

    【解决方案2】:

    这不是错误。

    • E:/ 表示您同时指定了一个驱动器一个目录

    • E:表示只指定一个驱动器,目录保留默认值。

    注意:现在人们认为的 current 目录实际上是 default 目录。即没有指定时默认应用的内容。 完全不指定驱动也是一样的,默认(当前默认)会适用。

    这是它在大多数文件系统上的工作方式。

    【讨论】:

    • 对默认目录感兴趣,不知道这个。您能否提供一个链接以阅读有关此内容的更多信息。但是,不管这个,file.exists() 仍然应该返回 true,这就是错误,所以我很抱歉,但在这方面我认为你错了。或者你对这种行为有解释吗?
    • “当前工作目录”这个术语已经使用了几十年,这就是为什么 pwd 命令不拼写为 pdd 的原因。现在尝试更改名称没有多大意义。
    • @EJP,那么也许你可以解释为什么在古老的 VMS 的命令语言(称为 DCL)中,cd 命令实际上是set default。顺便说一句,我需要提醒你,Windows 的首席架构师是 Dave Cuttler,也是 VMS 的架构师吗?
    • @gustf, file.exists() 如果没有指定,则添加默认目录,或者使用指定的目录(如果有)。但我同意你所做的所有观察,并且这种行为至少是不一致的。
    • @gustf,在 OpenVMS 上的示例,cd e:\ 将被调用为 set default e:\ 或实际上是 set default $E:[000000]Syntax
    猜你喜欢
    • 1970-01-01
    • 2011-07-13
    • 2013-12-17
    • 2013-05-04
    • 2011-09-28
    • 2017-07-23
    • 2012-09-15
    • 2017-03-22
    • 1970-01-01
    相关资源
    最近更新 更多