首页 > 解决方案 > 达到改变Java工作目录的效果

问题描述

上下文:我的软件依赖于调用一个库,由于旧的限制,该库只能接受相对路径作为输入。我需要相对于已知目录的路径。该库可能会在内部进行调用,例如

java.io.File fooBar = new java.io.File("foo/bar");

我需要这个给我/nwd/foo/bar,而不是说,运行的工作目录/cwd/foo/bar在哪里。/cwdjava

出于所有意图和目的,我无法修改该库的内部行为。手动覆盖实例化这些对象的方法将基本上涉及重写整个库。

一个诱人的解决方案是System.setProperty("user.dir", "/nwd")在调用库之前,但这实际上并没有给我想要的效果。实际上,如果我调用fooBar.getAbsolutePath(),我会得到想要的/nwd/foo/bar,但是如果我检查fooBar.exists()或尝试打开文件进行读取或写入,看起来该文件不存在,因为它实际上正在尝试打开/cwd/foo/bar. 事实上,如果fooBar被初始化为

java.io.File fooBar = new java.io.File(new java.io.File("foo/bar").getAbsolutePath());

这实际上会起作用,因为那时File对象实际上包含绝对引用。

在这一点上,我很沮丧,我不在乎这是否需要一个 hacky 解决方案。我只需要改变工作目录的效果。

标签: javarelative-pathworking-directory

解决方案


更改库的 CWD 的另一种方法是在不同的 Java 进程中启动它,您可以在启动时指定 CWD(参见例如ProcessBuilder文档)。如果我正确理解问题,您当前的流程有点类似于

 launch program with CWD 'a'
 use library X that expects CWD to be 'b' // <-- problem here

新流程将是

 launch program with CWD 'a'
 determine desired CWD for launching library X
 launch wrapper for library X with CWD 'b'
    internally, library X is happy because its CWD is as expected

当然,这将迫使您编写一个完整的包装器,并使用套接字和序列化或您选择的任何其他通信策略进行通信。从好的方面来说,这将允许您并排启动库的多个实例,而不会相互干扰它们的 CWD——以 JVM 和通信开销为代价。


推荐阅读