在user.dir中找不到文件

时间:2018-07-02 11:39:04

标签: java

我有一条简单的代码行,应该打印出文件的第一行:

System.out.println(new BufferedReader(new FileReader("file")).readLine());

带有此行的类文件位于c:/users/my/project中。 c:/users/my/project中存在一个名为“ file”的文件。 如果我打开CMD,请导航至c:/users/my/project并运行

java MyClass 

第一行打印出来,一切都很好。

但是,如果我在CMD中导航到C:/,然后运行

java -Duser.dir=c:/users/my/project MyClass

我得到一个响应,找不到文件“文件”。

如果我将“文件”移动到c:/并再次运行相同的命令,则会找到它。

据我了解,更改user.dir应该等同于我位于它所指向的文件夹中,但这似乎是正确的。该类文件位于user.dir中,但仍在我运行命令的文件夹中找到这些文件,而不是user.dir指向的文件夹。

这是为什么?

2 个答案:

答案 0 :(得分:1)

如果导航到另一个目录并尝试使用其他user.dir运行程序,则还必须设置类路径。您得到的错误是因为找不到类,不是因为找不到文件。

尝试

java -Duser.dir=c:/users/my/project -classpath c:/users/my/project MyClass

关于user.dir属性,请看File类的documentation。声明

  

路径名,无论是抽象的还是字符串形式的,都可以是绝对的或相对的。绝对路径名是完整的,因为不需要其他信息即可找到它表示的文件。相反,相对路径名必须根据从其他路径名获取的信息来解释。默认情况下,java.io包中的类始终针对当前用户目录解析相对路径名。该目录由系统属性user.dir命名,通常是在其中调用Java虚拟机的目录。

编辑

我在计算机上进行了测试,发现文件读取器在启动应用程序的目录中查找(可能与user.dir属性不一致)。见下文:

public static void main(String...args) {
    try {
        System.out.println("abs path to test.txt : " + new java.io.File("test.txt").getAbsolutePath());
        System.out.println("user home : " + System.getProperty("user.home"));
        System.out.println("user.dir : " + System.getProperty("user.dir"));
        System.out.println("running from : " + new java.io.File(".").getAbsolutePath());

        System.out.println(new java.io.BufferedReader(new java.io.FileReader("test.txt")).readLine());
    } catch (Exception e) {
        System.out.println("Not found");
    }
}

从没有文件的目录中启动它

C:\Users>java -Duser.home=C:\Users\william -Duser.dir=C:\Users\william -classpath C:\Users\william\Desktop Test
abs path to test.txt : C:\Users\william\test.txt
user home : C:\Users\william
user.dir : C:\Users\william
running from : C:\Users\william\.
Not found

从包含我要查找的文件的目录中启动它

C:\Users\william>java -Duser.home=C:\Users\william -Duser.dir=C:\Users\william -classpath C:\Users\william\Desktop Test
abs path to test.txt : C:\Users\william\test.txt
user home : C:\Users\william
user.dir : C:\Users\william
running from : C:\Users\william\.
hello world

另一项编辑

我正在使用openjdk 8,因此在我的情况下,其逻辑来自其来源:

FileReader 构造函数,带有String arg

public FileReader(String fileName) throws FileNotFoundException {
    super(new FileInputStream(fileName));
}

FileInputStream 构造函数

public FileInputStream(String name) throws FileNotFoundException {
    this(name != null ? new File(name) : null);
}

public FileInputStream(File file) throws FileNotFoundException {
    String name = (file != null ? file.getPath() : null);
    SecurityManager security = System.getSecurityManager();
    if (security != null) {
        security.checkRead(name);
    }
    if (name == null) {
        throw new NullPointerException();
    }
    if (file.isInvalid()) {
        throw new FileNotFoundException("Invalid file path");
    }
    fd = new FileDescriptor();
    fd.attach(this);
    path = name;
    open(name);
}

FileInputStream open(String)

private void open(String name) throws FileNotFoundException {
    open0(name);
}

open0(String)方法是本机调用(请参见下文)

private native void open0(String name) throws FileNotFoundException;

深入研究 FileInputStream.c

中的本机调用
JNIEXPORT void JNICALL
Java_java_io_FileInputStream_open0(JNIEnv *env, jobject this, jstring path) {
    fileOpen(env, this, path, fis_fd, O_RDONLY);
}

因此name成为本机path方法将使用的fileOpen。转换为file.getPath(),与file.getAbsolutePath()不同。

  

file.getPath()filenew File("test.txt")返回test.txt,可能找不到。

那是我能做的最好的事,希望对您有所帮助。

请参阅此bug report和此question。简而言之,通过命令行设置user.dir是个坏消息。

答案 1 :(得分:0)

您收到FileNotFound异常,因为程序无法找到您尝试读取的文件(在您的情况下,FileName也是“ file”)。

问题来了,因为您仅定义了文件名而不是路径。您应该提供绝对路径或相对路径,以使其在任何目录下都能正常工作。在没有路径定义的情况下,程序将尝试从命令执行所在的当前目录中读取文件。

让我们深入研究细节: 您在路径中有文本文件:c:/ users / my / project / file 您的路径中有Java文件:c:/ users / my / project / MyClass

现在,当您在c:/ users / my / project目录中运行时,由于仅在此目录中定义了文本文件“ file”,因此可以得到预期的输出。

当您切换到c:并尝试运行该程序时,会出现异常,因为它试图查找不存在的“ c:/ file”。

尝试更改该行以提及绝对路径:

System.out.println(new BufferedReader(new FileReader(“ c:/ users / my / project / file”))。readLine());