【问题标题】:FileNotFoundException when I have given the relative path to the properties file当我给出属性文件的相对路径时出现 FileNotFoundException
【发布时间】:2014-11-01 16:29:59
【问题描述】:

我正在尝试使用属性文件来存储我的数据库连接详细信息。当我创建一个 Java 应用程序并给出文件名时它起作用了,因为我将属性文件放在项目根文件夹中。

但是,当我在我的 Web 应用程序中尝试此操作时,我得到了 FileNotFoundException。我在项目节点下创建了一个 res 目录来保存属性文件。然后我将路径指定为“res/db.properties”,但出现异常。我也尝试将此文件放在配置文件目录下,但仍然遇到相同的异常。

这是我的代码 -

    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.FileNotFoundException;
    import java.io.InputStream;
    import java.util.Properties;

    /**
     *
     * @author aj
     */
    public class getConfigValues {

        public String[] getPropValues() {
            String[] props = new String[4];

            try {
                Properties prop = new Properties();
                String propFileName = "res/db.properties";

                InputStream input = null;

                input = new FileInputStream(propFileName);
                prop.load(input);

                props[0] = prop.getProperty("dbURL");
                props[1] = prop.getProperty("driverClass");
                props[2] = prop.getProperty("user");
                props[3] = prop.getProperty("password");

                return props;

            } catch (FileNotFoundException ip) {

                props[0] = "not found";

                return props;
            } catch (IOException i) {
                props[0] = "IO";

                return props;

            }

        }
    }

我在这里做错了什么?

【问题讨论】:

  • res 是源文件夹吗?直接尝试db.properties
  • 是的,我在发布之前已经尝试过了。我将res 添加为源包文件夹,然后运行Web 应用程序,但仍然得到FileNotFoundException。直接给出文件名也不起作用(那是我的第一个设置 - 项目根目录中的 prop 文件)。

标签: java fileinputstream properties-file


【解决方案1】:

您的主要错误是尝试加载带有文件相关类的资源。属性文件是应用程序的资源,因此应该相对于该应用程序放置

“相对”的意思是“在类路径中”。

在独立应用程序中,只需确保将这些资源的目录作为类路径的一部分提及即可。在 Web 应用程序中,WEB-INF/classes 目录已经是应用程序类路径的一部分。

现在是答案的第二部分:如何加载这些资源?简单地说:使用ClassLoader。它的职责不仅是加载类,还要加载资源(如属性文件)。

继续(省略异常处理):

ClassLoader loader = Thread.currentThread().getContextClassLoader();
URL resourceUrl = loader.getResource("res/db.properties");
Properties properties = new Properties();
try(InputStream input = resourceUrl.openStream()) {
    properties.load(input);
}
String[] result = new String[4];
...
return result;

【讨论】:

    【解决方案2】:
    • 作为 Web 应用程序,您无法预测当前的工作目录,因此使用相对路径总是会有问题;
    • 根据 Web 应用程序的打包方式,您的属性文件甚至可能不是文件系统对象。它很可能是隐藏在 .war 文件中的资源。

    访问此文件的一种可靠方法是将其构建到 Web 应用程序的 WEB-INF 目录中。然后您可以使用javax.servlet.ServletContext.getResourceAsStream("WEB-INF/res/db.properties") 访问它。

    或者,您可以将其构建到 WEB-INF/classes 目录中并使用 java.lang.ClassLoader.getResourceAsStream("/res/db.properties") 加载它。

    【讨论】:

    • 一个java进程一旦启动,就不能改变它的当前目录。 “getRessource”函数是搜索文件的最佳方式。
    • @Steve 注意到 - 谢谢!按照this question 中的建议,我能够解决我的问题。但我仍有疑问。这与仅将我的连接详细信息放在变量中并使用它们有什么不同?如果我遵循这种方法,我将不得不替换 WAR 文件并重新部署。我使用 prop 文件的想法是,我可以使用它并有效地更改数据库连接细节,而无需重新部署整个应用程序。
    • 现在您提出了一个更好的问题!通常的策略是在您的应用程序服务器中配置一个 DataSource,查找(或将其注入)到您的应用程序中,然后使用它来提供数据库连接。这会将所有与连接相关的信息放在服务器配置中,而不是您的应用程序中。
    【解决方案3】:

    当您将其作为 Web 应用程序运行时,当前目录很可能是不同的...有一个系统属性会告诉您当前目录是什么。或者你可以使用 Class.getResource 来使用你的类路径来找到 res 目录

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-31
      • 2013-03-04
      • 2011-08-23
      • 2011-03-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多