当我运行一个应该从 Eclipse 中的文件读取的 Java 应用程序时,我得到一个java.io.FileNotFoundException
,即使该文件位于正确的目录中。我可以从命令行编译和运行应用程序就好了;该问题仅发生在 Eclipse 中,具有多个项目和应用程序。是否需要更改运行配置或构建路径以使其正确找到文件的设置?
5 回答
问题很可能是您的应用程序使用了相对路径名。正如@BalusC 所说,相对路径名可能有问题。但是 IMO,当他说“[你]你永远不应该在 java.io 的东西中使用相对路径”时,他走得太远了。
当应用程序使用(例如)FileInputStream(File)
构造函数打开文件时,相对路径名将在 .javadoc 中描述的过程中相对于“当前目录”进行解析,如下所述File.getAbsolutePath()
。
[...]否则,此路径名将以系统相关的方式解析。在 UNIX 系统上,通过根据当前用户目录解析相对路径名,使其成为绝对路径名。在 Microsoft Windows 系统上,通过将相对路径名解析为由路径名命名的驱动器的当前目录(如果有),从而使相对路径名成为绝对路径;如果不是,则针对当前用户目录进行解析。
因此,我们立即看到“当前目录”的概念在 Windows 和 UNIX 平台上有不同的细微差别。第二个问题是,在纯 Java 中,您无法确定当前目录是什么,而且您当然无法为使用纯 Java 的当前 JVM 更改它。(当 JVM 启动时,“user.dir”系统属性设置为当前目录,但没有什么可以阻止应用程序更改属性,因此您不能完全依赖它。此外,更改“user.dir”只会更改解决空路径的方式,而不是一般的相对路径。)
那么你应该怎么做呢?
一种选择是使用绝对路径名来引用文件。这在(几乎)所有情况下都是可靠的,但是如果用户必须输入路径名,或者如果您需要避免硬连线(或配置)绝对路径名,则使用绝对路径名可能会出现问题。
第二种选择是使用类路径相对路径名并定位相对于应用程序安装目录的文件。如果这是您需要做的,这可以工作,但如果您需要将 a 传递
File
给某个库方法,则会出现问题。如果您试图查找用户的应用程序首选项,它也无济于事。(一般情况下,将用户偏好放入安装目录是错误的......)第三种选择是相对于您从其他地方获得的某个绝对目录来命名文件;例如
new File(System.getProperty("home.dir"), "foo/bar");
。最后一个选项是使用相对路径名,并假设用户知道当前目录是什么。对于用户从命令行运行的许多应用程序,这是正确的解决方案。
在 Eclipse 的特殊情况下,有一个简单的解决方案。转到用于启动应用程序的“运行配置”,打开“参数”选项卡,然后单击“其他”单选按钮。然后输入一个绝对路径名作为启动应用程序的工作目录。当子 JVM 启动时,它会将指定的工作目录作为其当前目录。
另一种选择是简单地找出“当前路径”在您的环境中指向的目录——不管它是什么。一旦你弄清楚了,你可以从那里选择你的解决方案。也许那是使用适当的相对路径指向您的文件位置或重新定位文件。
File testFile = new File("");
String currentPath = testFile.getAbsolutePath();
System.out.println("current path is: " + currentPath);
在 Eclipse 中创建默认 Java 应用程序时,您将获得以下目录结构:
./ProjectName/ - 根目录
./ProjectName/bin/ - 输出目录,包含 .class 文件
./ProjectName/src/ - 源目录,包含 .java 文件
如果您的应用程序请求“./data.txt”,它将相对于根目录搜索它。这是“工作目录”,可以根据上面 Martin 的回复在参数选项卡中进行配置。
你说它可以从命令行工作?这可能是因为您在运行 java 二进制文件时位于 bin 或 src 文件夹中。在这种情况下,工作目录是命令提示符当前所在的目录。例如,如果您进入 /src/ 目录,javac *.java
然后从那里运行文件,它将在 /src/ 目录中搜索“./data.txt”。如果您进入 /bin/ 目录并从那里运行您的应用程序,它将查找相对于 /bin/ 目录的文件。
我遇到了类似的问题,我将文件放在 src 文件夹内名为 cobolcopybooks 的文件夹中,并尝试使用 classloader.getResource("cobolcopybooks/demostud.cob") 在我的项目中访问它们,但我得到空指针异常,我在几次尝试失败后,通过清理和构建工作区尝试了几次,我意识到我没有刷新项目以允许文件与项目一起构建。即这些文件应该与其他类文件一起可见,因为在运行时根目录将是 bin 目录,它正在那里搜索这些文件。
假设用户没有输入文件的完整文件路径并输入类似“myfilenameonly”的内容。
File file = new File(".", args[0])
在这种情况下需要定位文件(注意传递的第一个参数)。
所有平台:File.getParent()
不返回父目录,它应该以文件系统特定的方式返回“..”或父目录的名称。
例如,如果您创建文件“myfilenameonly”而不指定其所在目录的完整路径,则File.getParent()
将返回 null。
进一步查看:http ://bugs.sun.com/bugdatabase/view_bug.do?bug_id=1228537