简单的Java桌面应用程序:配置文件以及放置它们的位置

时间:2016-08-19 14:51:44

标签: java eclipse scala relative-path

这感觉就像一个绝对的新手问题,但我对于应该是一个基本问题的人来说是一个巨大的傻瓜。

我正在用Java编写一个简单的桌面应用程序。 (事实上​​,Scala,但让它通过。)它针对Windows机器。我想打包它,让它在没有创建安装程序的情况下运行,或者搞乱Windows注册表。我想要一个用户可以查找和编辑的配置文件,以便自定义设置。 (例如,以SublimeText的用户首选项的方式。)

我设想了以下结构:

my-application/
|- bin/
   |- myApp.class (or myApp.jar, if you prefer)
|- files/
   |- config/
      |- config.json
   |- output/
      |- output.xlsx
|-runMyApp.bat

在Eclipse中,相对路径倾向于解析到myApplication/目录,但是如果我从命令行运行应用程序,它们将解析为-cp参数。 (通常是bin/目录。)

我天真吗?我完全得错了范例吗?

在我看来,能够在可执行文件周围的文件系统中一致地定位文件(资源)是一件非常重要的事情。

请帮忙!

2 个答案:

答案 0 :(得分:6)

打包应用程序意味着将类放在.jar文件中,该文件是一个zip文件,其中包含一个或多个特殊的Java特定条目。 (有许多Stack Overflow答案描述了如何执行此操作,例如Java: export to an .jar file in eclipse。可以随意搜索更多内容。)

问题是,应用程序无法写入自己的.jar文件。在Windows上,该文件可能被锁定且不可写入;在其他系统上,它可能是有可能的,但出于很多原因是一个坏主意。您应该始终将.jar文件视为只读。

由于配置需要是可写的,因此它不能存在于.jar文件中,但是.jar文件可以(并且应该)将config.json包含为默认配置。实际配置应该是用户主目录下的某个文件;如果它不存在,您的程序应将您的默认配置复制到该位置以允许将来修改。或者,您的程序可以忽略缺少的配置并默认读取内部打包的默认配置,但在这种情况下,您希望为最终用户提供可写配置文件格式的完整文档,因为它们没有示例过去。

打包在.jar文件中的文件称为 resources ,并使用Class.getResourceClass.getResourceAsStream方法读取。您无法使用File或Path对象读取它们,因为它们是zip存档的一部分,而不是实际文件。将其复制到可写位置通常如下所示:

Path userConfigFile = /* ... */;

try (InputStream defaultConfig = getClass().getResourceAsStream("/config/config.json")) {
    Files.copy(defaultConfig, userConfigFile);
}

有关阅读资源的更多信息,您可能需要阅读Access to Resources

在Windows上,配置文件的实际位置通常位于用户AppData目录的子目录中:

Path configParent;

String appData = System.getEnv("APPDATA");
if (appData != null) {
    configParent = Paths.get(appData);
} else {
    configParent = Paths.get(
        System.getProperty("user.home"), "AppData", "Local");
}

Path configDir = configParent.resolve(applicationName);
Files.createDirectories(configDir);

Path userConfigFile = configDir.resolve("config.json");

如果您对讨论在其他平台上放置用户配置文件的位置感兴趣,请参阅this questionthis one

答案 1 :(得分:1)

File默认在用户的当前工作目录中解析相对路径(可用作系统属性user.dir)。因此,如果您在命令行上cd更改为目录,然后调用Java应用程序,则从Java应用程序的角度来看,该目录将是当前用户的工作目录。

您可以做的一件事是将您的base-directory作为系统属性传递给Java应用程序。这可以在shell脚本中完成,该脚本通过使用它自己的位置来启动应用程序。

另一种可能性是在调用Java应用程序时在类路径中包含配置文件等文件,并在Java应用程序中从类路径加载它们。这种解决方案的缺点是,用户可以做更多的事情而不是损坏作为可能的结果。