JavaFX:Editable 打包后的配置文件

JavaFX:Editable Configuration Files After Packaging

我有一个 JavaFX 应用程序,我使用 antBuild 将其打包以构建单个安装程序 .exe 文件,我的应用程序有一些配置文件放置在项目的根目录中,我通过这种方式从根目录加载它们项目以便它们可以放在 .jar 文件旁边并且可以更改:

        try {
        File base = null;
        try {
            base = new File(MainApp.class.getProtectionDomain().getCodeSource().getLocation().toURI())
                    .getParentFile();
        } catch (URISyntaxException e) {
            System.exit(0);
        }
        try {
            File configFile = new File(base, "config.properties");
        }

所以打包应用后,即使我手动将文件与 jar 文件放在同一个地方,应用也无法识别它们并出错。


那么什么是正确的存储方式和存储某种配置文件的位置以及如何将它们添加到安装程序以在安装过程中将其放在正确的位置?

如果您的应用程序被捆绑为一个 jar 文件,那么 MainApp.class.getProtectionDomain().getCodeSource().getLocation().toURI() 将 return 一个 jar: 方案 URI。 constructor for File taking a URI 假定它获得了一个 file: 方案 URI,这就是您在此处收到错误的原因。 (基本上,如果您的应用程序被捆绑为一个 jar 文件,则 resource config.properties 根本不是一个文件,它是存档文件中的一个条目。)基本上没有 (可靠)更新捆绑应用程序的 jar 文件内容的方法。

我通常的做法是将默认的配置文件打包到jar文件中,然后在用户文件系统上定义一个路径,用来存放可编辑的配置文件。通常这将相对于用户的主目录:

Path configLocation = Paths.get(System.getProperty("user.home"), ".applicationName", "config.properties");

或类似的东西。

然后在启动时你可以做:

if (! Files.exists(configLocation)) {
    // create directory if needed
    if (! Files.exists(configLocation.getParent())) {
        Files.createDirectory(configLocation.getParent());
    }

    // extract default config from jar and copy to config location:

    try (
        BufferedReader in = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("/config.properties")));
        BufferedWriter out = Files.newBufferedWriter(configLocation);) {

        in.lines().forEach(line -> {
            out.append(line);
            out.newLine();
        });
    } catch (IOException exc) {
        // handle exception, e.g. log and warn user config could not be created
    }
}

Properties config = new Properties();
try (BufferedReader in = Files.newBufferedReader(configLocation)) {
    config.load(in);
} catch (IOException exc) {
    // handle exception...
}

所以这会检查配置文件是否已经存在。如果没有,它会从 jar 文件中提取默认配置并将其内容复制到定义的位置。然后它从定义的位置加载配置。因此,用户第一次运行应用程序时,它使用默认配置。之后,用户可以编辑配置文件,随后它将使用编辑后的版本。如果您愿意,您当然可以创建一个 UI 来修改内容。这样做的一个好处是,如果用户做了一些使配置不可读的事情,他们可以简单地删除它,然后将再次使用默认值。

显然这可以更好地防止异常(例如处理目录由于某种原因不可写的情况,使配置文件位置用户可定义等)但这是我在这些中使用的基本结构场景。