java - 简单的 Java 桌面应用程序 : Config files and where to put them

标签 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/ 目录。)

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

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

请帮忙!

最佳答案

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

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

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

打包在 .jar 文件中的文件称为 资源 并使用 Class.getResource 读取或 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");

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

关于java - 简单的 Java 桌面应用程序 : Config files and where to put them,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39042024/

相关文章:

scala - 改进 Scala 的 JVM

scala - 为什么 `Left` 和 `Right` 有两个类型参数?

JAVA浮点运算

android - 如何在 android 的 webview 中播放 youtube 视频?

eclipse - Eclipse 中 Maven Spring Boot 项目的部署程序集

java - org.apache.tomcat.util.bcel.classfile.ClassFormatException : Invalid byte tag in constant pool: 15

java - (编译:compileIncremental) javac returned nonzero exit code

java - 从 java.util.TimeZone 转换为 org.joda.DateTimeZone

java - java中如何终止正在运行的循环?

Java Inetaddress getallbyname 错误