简单 Java 桌面应用程序:配置文件及其放置位置

Simple Java Desktop App: Config files and where to put them

这感觉像是一个绝对的新手问题,但我正在为什么应该是一个基本问题而大费周折。

我正在 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/ 目录。)

我是不是太天真了?我是不是完全弄错了范式?

在我看来,能够在可执行文件周围的文件系统中始终如一地定位文件(资源)是一件基本的事情。

请帮忙!

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

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

另一种可能性是在调用 Java 应用程序时将配置文件等文件包含在 classpath 中,并从 Java 应用程序中的 classpath 加载它们。此解决方案的缺点是用户可以做比需要更多的事情,并可能导致损坏。

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

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

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

打包在 .jar 文件中的文件称为 resources 并使用 Class.getResource or Class.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");

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