Java:File.exists()设置“时不一致”;user.dir";

Java:File.exists()设置“时不一致”;user.dir";,java,filesystems,Java,Filesystems,JRE 6,在Windows XP上 使用不同的构造函数实例化两个文件对象会导致File.exists()方法中的结果不一致 免责声明:下面的代码是抽象代码,不是实际代码。我认为这根本不是文件分隔符问题。我首先要求得到早期反应,以防我错过了一个很好理解的问题。现在看来,重置user.dir系统属性是导致此问题的原因之一。下面的代码现在是可复制和可用的。您可以复制/粘贴Java类并进行尝试,它的行为应该与我列出的结果一致 设置: public class TestFileExists {

JRE 6,在Windows XP上

使用不同的构造函数实例化两个文件对象会导致
File.exists()
方法中的结果不一致

免责声明:下面的代码是抽象代码,不是实际代码。我认为这根本不是文件分隔符问题。我首先要求得到早期反应,以防我错过了一个很好理解的问题。现在看来,重置
user.dir
系统属性是导致此问题的原因之一。下面的代码现在是可复制和可用的。您可以复制/粘贴Java类并进行尝试,它的行为应该与我列出的结果一致

设置:

public class TestFileExists {

    public static void main(String[] args) {

        System.setProperty("user.dir", "C:\\toto\\");

        File root = new File("tmp");

        File sub_a = new File(root, "sub");

        File sub_b = new File(root.getAbsolutePath()+"/sub");

        System.out.println("sub_a path ? "+sub_a.getAbsolutePath());
        System.out.println("sub_a exists ? "+sub_a.exists());
        System.out.println("sub_b path ? "+sub_b.getAbsolutePath());
        System.out.println("sub_b exists ? "+sub_b.exists());
        System.out.println("Path equals ? "+ (sub_a.getAbsolutePath().equals(sub_b.getAbsolutePath())));
        System.out.println("Obj equals ? "+ (sub_a.equals(sub_b)));

    }

}
sub_a path ? C:\toto\tmp\sub
sub_a exists ? false
sub_b path ? C:\toto\tmp\sub
sub_b exists ? true
Path equals ? true
Obj equals ? false
创建文件夹体系结构
C:\toto\tmp\sub

从不包含
tmp/sub
子文件夹体系结构的任何文件夹中启动以下类

代码:

public class TestFileExists {

    public static void main(String[] args) {

        System.setProperty("user.dir", "C:\\toto\\");

        File root = new File("tmp");

        File sub_a = new File(root, "sub");

        File sub_b = new File(root.getAbsolutePath()+"/sub");

        System.out.println("sub_a path ? "+sub_a.getAbsolutePath());
        System.out.println("sub_a exists ? "+sub_a.exists());
        System.out.println("sub_b path ? "+sub_b.getAbsolutePath());
        System.out.println("sub_b exists ? "+sub_b.exists());
        System.out.println("Path equals ? "+ (sub_a.getAbsolutePath().equals(sub_b.getAbsolutePath())));
        System.out.println("Obj equals ? "+ (sub_a.equals(sub_b)));

    }

}
sub_a path ? C:\toto\tmp\sub
sub_a exists ? false
sub_b path ? C:\toto\tmp\sub
sub_b exists ? true
Path equals ? true
Obj equals ? false
结果:

public class TestFileExists {

    public static void main(String[] args) {

        System.setProperty("user.dir", "C:\\toto\\");

        File root = new File("tmp");

        File sub_a = new File(root, "sub");

        File sub_b = new File(root.getAbsolutePath()+"/sub");

        System.out.println("sub_a path ? "+sub_a.getAbsolutePath());
        System.out.println("sub_a exists ? "+sub_a.exists());
        System.out.println("sub_b path ? "+sub_b.getAbsolutePath());
        System.out.println("sub_b exists ? "+sub_b.exists());
        System.out.println("Path equals ? "+ (sub_a.getAbsolutePath().equals(sub_b.getAbsolutePath())));
        System.out.println("Obj equals ? "+ (sub_a.equals(sub_b)));

    }

}
sub_a path ? C:\toto\tmp\sub
sub_a exists ? false
sub_b path ? C:\toto\tmp\sub
sub_b exists ? true
Path equals ? true
Obj equals ? false
我不明白行
sub_a是否存在?false
,并且结果在机器之间不一致,也不与根初始路径ant一致。现在,结果与机器之间的一致

现在,如果您通过从命令行调用java从包含
tmp/sub
子文件夹体系结构的文件夹重新执行该类(例如,如果您从
D:\
调用它,具有
D:\tmp\sub
),您将获得预期的:

sub_a path ? C:\toto\tmp\sub
sub_a exists ? true
sub_b path ? C:\toto\tmp\sub
sub_b exists ? true
Path equals ? true
Obj equals ? false
但是
sub_a
的存在显然是误报,因为它检查的是另一个文件夹的存在,而不是
getAbsolutePath()
所描述的文件夹

因此我强烈怀疑
File.exists()
依赖于实际的Java执行路径,并且文件存在与绝对路径不一致,并且
exists()
使用“user.dir”系统属性以外的另一个路径来检查文件系统

知道这个问题可能来自哪里吗?

在这行:

File sub_b = new File(root.getAbsolutePath()+"/sub");
您应该使用常量
File.separator(取决于基础系统),而不是硬编码的正斜杠。

在这一行:

File sub_b = new File(root.getAbsolutePath()+"/sub");

您应该使用常量
文件.separator
(取决于基础系统),而不是硬编码的正斜杠。

我认为它是目录分隔符,因为Windows通常使用反斜杠“\”,而Linux使用普通斜杠“/”

尝试将行更改为:

File sub_b = new File(root.getAbsolutePath() + System.getProperty("file.separator") + "sub");

我认为这是目录分隔符,因为Windows通常使用反斜杠“\”而Linux使用普通斜杠“/”

尝试将行更改为:

File sub_b = new File(root.getAbsolutePath() + System.getProperty("file.separator") + "sub");

这可能是文件分隔符问题。在Windows上,标准的文件分隔符是反斜杠(
\
)。当您创建
sub_b
时,您将创建一个包含斜杠和反斜杠的路径名(作为
字符串)。系统可能对此有点困惑。

这可能是文件分隔符问题。在Windows上,标准的文件分隔符是反斜杠(
\
)。当您创建
sub_b
时,您将创建一个包含斜杠和反斜杠的路径名(作为
字符串)。系统可能会对此有点困惑。

这些结果应该是跨机器确定的。让我把它按行分解:

System.out.println("sub_a exists ? "+sub_a.exists());
在这里,您要问的是这个文件是否确实存在于文件系统中。假设该文件存在,则应始终返回相同的值

System.out.println("sub_b exists ? "+sub_b.exists());
同样的事情。您正在检查此文件是否确实存在

System.out.println("Path equals ? "+ (sub_a.getAbsolutePath().equals(sub_b.getAbsolutePath())));
这里你看到的是绝对路径是否相同

System.out.println("Obj equals ? "+ (sub_a.equals(sub_b)));
在这里,您正在与.equals()进行对象比较,它将调用FileSystem类对两个对象的路径对象进行比较(),而不是绝对路径

很可能是文件分隔符错误。尝试在sub_b的构造中替换File.separator,如下所示:

File sub_b = new File(root.getAbsolutePath()+File.separator+"sub");

这些结果应该是跨机器确定的。让我把它按行分解:

System.out.println("sub_a exists ? "+sub_a.exists());
在这里,您要问的是这个文件是否确实存在于文件系统中。假设该文件存在,则应始终返回相同的值

System.out.println("sub_b exists ? "+sub_b.exists());
同样的事情。您正在检查此文件是否确实存在

System.out.println("Path equals ? "+ (sub_a.getAbsolutePath().equals(sub_b.getAbsolutePath())));
这里你看到的是绝对路径是否相同

System.out.println("Obj equals ? "+ (sub_a.equals(sub_b)));
在这里,您正在与.equals()进行对象比较,它将调用FileSystem类对两个对象的路径对象进行比较(),而不是绝对路径

很可能是文件分隔符错误。尝试在sub_b的构造中替换File.separator,如下所示:

File sub_b = new File(root.getAbsolutePath()+File.separator+"sub");

文件
可以表示抽象路径。为
tmp
创建
文件
和从
tmp
的绝对路径创建一个
文件
将不会相等
对象,尽管它们的绝对路径相等

我不确定sub_a是否不存在,但sub_b是否存在,但我怀疑这是否是一个分隔符问题。我怀疑这与以下声明有关:

每个路径名字符串都转换为抽象路径名,子抽象路径名根据父抽象路径名解析

我不知道在基于Unix的文件系统中,从
/full/path/to
/tmp/sub
将存在,但
/full/path/to/tmp
将不存在


如果问题在系统之间是一致的,则可以通过转储更多每个
文件
对象的状态来更清楚地理解问题,而不仅仅是打印比较。

文件
可以表示抽象路径。为
tmp
创建
文件
和从
tmp
的绝对路径创建一个
文件
将不会相等
对象,尽管它们的绝对路径相等

我不确定sub_a是否不存在,但sub_b是否存在,但我怀疑这是否是一个分隔符问题。我怀疑这与以下声明有关:

每个路径名字符串都是conv