解决此问题的实际方法是将 EXE 捆绑为类路径资源。看来你已经安排好了。
使用类路径资源时,成熟的程序不应假定资源在文件系统中。资源可以打包在 JAR 文件中,甚至可以打包在 WAR 文件中。那时您唯一可以信任的是在 Java 中访问资源的标准方法,如下所示。
Class.getResourceAsStream
那么,解决问题的方法是使用调用(或)的事实标准访问资源内容ClassLoader.getResourceAsStream
,将内容保存到临时文件,然后从该文件执行。这将保证您的程序无论其包装如何都能正常工作。
换句话说:
- 调用
getClass().getResourceAsStream("/program.exe")
. 从静态方法中,您不能调用getClass
,因此请改用当前类的名称,如MyClass.class.getResourceAsStream
. 这将返回一个InputStream
.
- 创建一个临时文件,最好使用
File.createTempFile
. 这将返回一个File
标识新创建文件的对象。
- 打开
OutputStream
这个临时文件。
- 使用这两个流将数据从资源复制到临时文件中。
IOUtils.copy
如果您喜欢 Apache Commons 工具,则可以使用。完成此步骤后,不要忘记关闭两个流。
- 执行这样存储在临时文件中的程序。
- 清理。
换句话说(后来添加的代码片段):
private void executeProgramFromClasspath() throws IOException {
// Open resource stream.
InputStream input = getClass().getResourceAsStream("/program.exe");
if (input == null) {
throw new IllegalStateException("Missing classpath resource.");
}
// Transfer.
OutputStream output = null;
try {
// Create temporary file. May throw IOException.
File temporaryFile = File.createTempFile(getClass().getName(), "");
output = new FileOutputStream(temporaryFile);
output = new BufferedOutputStream(output);
IOUtils.copy(input, output);
} finally {
// Close streams.
IOUtils.closeQuietly(input);
IOUtils.closeQuietly(output);
}
// Execute.
try {
String path = temporaryFile.getAbsolutePath();
ProcessBuilder processBuilder = new ProcessBuilder(path);
Process process = processBuilder.start();
process.waitFor();
} catch (InterruptedException e) {
// Optional catch. Keeps the method signature uncluttered.
throw new IOException(e);
} finally {
// Clean up
if (!temporaryFile.delete()) {
// Log this issue, or throw an error.
}
}
}