小编典典
解决此问题的实际方法是将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.
}
}
}
2020-11-23