これを解決するための事実上のアプローチは、EXEをクラスパスリソースとしてバンドルすることです。あなたはすでにこれを手配したようです。
クラスパスリソースを使用する場合、成熟したプログラムは、リソースがファイルシステムにあると想定してはなりません。リソースは、JARファイル、またはWARファイルにパッケージ化することもできます。その時点で信頼できる唯一のものは、以下に示すように、Javaでリソースにアクセスするための標準的な方法です。
問題を解決する方法は、デファクトスタンダードの呼び出しClass.getResourceAsStream
(またはClassLoader.getResourceAsStream
)を使用してリソースの内容にアクセスし、その内容を一時ファイルに保存して、そのファイルから実行することです。これにより、パッケージに関係なく、プログラムが正しく機能することが保証されます。
言い換えると:
- 呼び出す
getClass().getResourceAsStream("/program.exe")
。静的メソッドからは呼び出すことができないgetClass
ため、代わりに、のように現在のクラスの名前を使用してくださいMyClass.class.getResourceAsStream
。これはを返しますInputStream
。
- できればを使用して、一時ファイルを作成します
File.createTempFile
。File
これにより、新しく作成されたファイルを識別するオブジェクトが返されます。
OutputStream
この一時ファイルを開きます。
- 2つのストリームを使用して、リソースから一時ファイルにデータをコピーします。
IOUtils.copy
ApacheCommonsツールに興味がある場合に使用できます。この手順が完了したら、2つのストリームを閉じることを忘れないでください。
- このようにして一時ファイルに保存されているプログラムを実行します。
- 掃除。
言い換えれば(コードスニペットは後で追加されます):
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.
}
}
}