我有一条简单的代码行,应该打印出文件的第一行:
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
指向的文件夹。
这是为什么?
答案 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()
,file
为new 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());