当我运行应该从Eclipse中的文件读取的Java应用程序时,我会得到一个 java.io.FileNotFoundException, ,即使文件在正确的目录中。我可以从命令行中编译并运行该应用程序,很好。该问题仅发生在Eclipse中,有一个以上的项目和应用。我是否需要在运行配置或构建路径上更改设置以正确找到文件?

有帮助吗?

解决方案

问题很可能是您的应用程序使用相对路径名。正如@balusc所说,相对路径名可能是有问题的。但是IMO,当他说的时候他走得太远 “[你应该 绝不 在Java.io中使用相对路径”.

当应用程序使用(例如) FileInputStream(File) 构造函数,相对路径名相对于“电流目录”在所描述的Javadoc中所述的过程中解析 File.getAbsolutePath().

...]否则,该路径名是以系统依赖性方式解决的。在UNIX系统上,通过将其解决针对当前用户目录来制作相对路径名。在Microsoft Windows Systems上,将相对路径名用于通过将路径名的当前目录(如果有)命名的驱动器的当前目录来制作。如果没有,则可以根据当前的用户目录解决。

因此,我们立即看到“当前目录”的概念在Windows和Unix平台上具有不同的细微差别。第二个问题是,在纯Java中,您无法明确地找出当前目录是什么,并且您当然不能使用纯Java为当前的JVM更改它。 (当JVM启动时,“ user.dir”系统属性设置为当前目录,但是 没有什么可以阻止应用程序更改属性 因此,您不能完全依靠它。此外,更改“ user.dir”仅改变了空路的解决方式,而不是相对路径。)

那你该怎么办?

  • 一种选择是使用绝对路径名来参考文件。这在(几乎)所有情况下都是可靠的,但是如果用户必须输入路径名,或者需要避免使用硬接线(或配置)的绝对路径名,则使用绝对路径名可能会出现问题。

  • 第二个选项是使用ClassPath相对路径名并找到相对于应用程序安装目录的文件。如果您需要做的话,这有效,但是如果您需要通过 File 到某些库方法。如果您试图找到用户的应用程序首选项,也无济于事。 (通常,将用户首选项放入安装目录是一个错误...)

  • 第三个选项是将文件命名相对于您从其他地方获得的某些绝对目录命名;例如 new File(System.getProperty("home.dir"), "foo/bar");.

  • 最终选项是使用相对路径名,并假设用户知道当前目录。对于用户从命令行运行的许多应用程序,这是正确的解决方案。

在日食的特殊情况下,有一个简单的解决方案。转到您使用的“运行配置”来启动应用程序,打开“参数”选项卡,然后单击“其他”广播按钮。然后输入一个绝对路径名作为启动应用程序的工作目录。启动儿童JVM时,它将以指定的工作目录为当前目录。

其他提示

另一个选择是简单地弄清楚“当前路径”指向您的环境中的目录 - 无论是什么。一旦弄清楚,就可以从那里选择解决方案。也许那是使用适当的相对路径到您的文件的位置或重新定位文件。

    File testFile = new File("");
    String currentPath = testFile.getAbsolutePath();
    System.out.println("current path is: " + currentPath);

当您在Eclipse中创建默认Java应用程序时,您将获得此目录结构:

。/项目名称/ - 根目录
./projectName/bin/ - 输出目录,包含.class文件
./projectName/src/ - 源目录,包含.java文件

如果您的应用程序请求“ ./data.txt”,它将相对于根目录进行搜索。这是“工作目录”,可以按照上面的Martin答复在“参数”选项卡中配置。

您说它可以从命令行工作吗?这可能是因为运行Java二进制时,您要么在垃圾箱或SRC文件夹中。在这种情况下,工作目录是命令提示符当前内部的目录。例如,如果您进入 / src /目录,请说 javac *.java 然后从那里运行文件,它将在/src/Directory中搜索“ ./data.txt”。如果您进入 / bin / Directory内部并从那里运行您的应用程序,它将查找相对于 / bin / Directory的文件。

你应该 绝不 使用相对路径 java.io 东西。该路径将取决于当前的工作目录,这取决于您启动应用程序的方式,因此在所有环境上都不相同。这是从Java应用程序内部无法控制的。便携性麻烦!始终使用绝对路径。因此,例如 c:/path/to/file.ext 或者 /path/to/file.ext (带有领先的斜杠)用于Unix和Consorts(甚至是磁盘字母无关紧要的时候)。

每当您想将某些文件与应用程序一起运送时,一个常见的做法是将它们放在 classpath 也是。这样您就可以使用 ClassLoader#getResource() 获取其位置。它返回 URL. 。您可以使用 URL#toURI() 或者 URL#getPath() 并将其传递给构造函数 java.io.File 然后以通常的方式进一步使用它。

在您的日食项目中 src 文件夹(您的Java源所在的位置)基本上是类路径的根。此外,它当然还涵盖了所有其他项目和(外部)文件夹 建立路径.

假设您已将特定文件放在 班级路径:

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
URL url = classLoader.getResource("file.ext");
File file = new File(url.getPath());
FileInputStream input = new FileInputStream(file);
// ...

你甚至可以使用 ClassLoader#getResourceAsStream() 直接得到 InputStream:

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("file.ext");
// ...

如果将其放置在包装中,则可以使用通常的路径名:

URL url = classLoader.getResource("com/example/file.ext");
// ...

或者

InputStream input = classLoader.getResourceAsStream("com/example/file.ext");
// ...

我遇到了类似的问题,我将文件放在一个名为cobolcopybooks的文件夹中,并试图使用classLoader.getResource(“ cobolcopybooks/demostud.cob”)尝试在我的项目中访问它们),但是我得到了无效的指针,我又有零点在几次失败的尝试后,我意识到我没有刷新项目以允许文件与项目一起构建后,通过清洁和构建工作区进行了几次尝试。即这些文件应与其他类文件一起可见,因为在运行时,根目录将是bin目录,并且正在搜索那里的这些文件。

假设用户未输入到文件的完整文件路径并输入诸如“ myfilenameyly”之类的内容。File file = new File(".", args[0]) 在这种情况下,需要找到文件(请注意第一个参数通过)。

所有平台: File.getParent() 不要返回父目录,它应该以特定于文件系统的方式返回“ ..”或父级目录的名称。

如果创建文件“ myfilenameonly”而未指定通往其位置目录的完整路径,则 File.getParent(), ,例如,将返回null。

进一步参见: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=1228537

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top