質問
Javaプログラムを通じてexeを実行しています。パスは Java でハードコードされています。
exeをjarにパッケージしました。
しかし、Javaファイルにパス名がハードコードされているため、行き詰まっています。そのため、jar をスタンドアロン プログラムとして実行できません。
内部にexeを持ち、スタンドアロンプログラムとして実行できるような瓶をパッケージ化するためのヒントはありますか?
ありがとう、クリス
解決
奇妙なことに、今朝も同様のコードを書かなければなりません...それを成し遂げるよう後押ししてくれてありがとう:-)
これにより、 .exe
ローカル ディスク上のローカル ファイルにコピーされます。Java プログラムが存在する場合、ファイルは削除されます。
編集:おっと、実際にファイルをコピーするのを忘れていました...
import java.io.Closeable;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.security.CodeSource;
import java.security.ProtectionDomain;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
public class Main
{
public static void main(final String[] args)
throws URISyntaxException,
ZipException,
IOException
{
final URI uri;
final URI exe;
uri = getJarURI();
exe = getFile(uri, "Main.class");
System.out.println(exe);
}
private static URI getJarURI()
throws URISyntaxException
{
final ProtectionDomain domain;
final CodeSource source;
final URL url;
final URI uri;
domain = Main.class.getProtectionDomain();
source = domain.getCodeSource();
url = source.getLocation();
uri = url.toURI();
return (uri);
}
private static URI getFile(final URI where,
final String fileName)
throws ZipException,
IOException
{
final File location;
final URI fileURI;
location = new File(where);
// not in a JAR, just return the path on disk
if(location.isDirectory())
{
fileURI = URI.create(where.toString() + fileName);
}
else
{
final ZipFile zipFile;
zipFile = new ZipFile(location);
try
{
fileURI = extract(zipFile, fileName);
}
finally
{
zipFile.close();
}
}
return (fileURI);
}
private static URI extract(final ZipFile zipFile,
final String fileName)
throws IOException
{
final File tempFile;
final ZipEntry entry;
final InputStream zipStream;
OutputStream fileStream;
tempFile = File.createTempFile(fileName, Long.toString(System.currentTimeMillis()));
tempFile.deleteOnExit();
entry = zipFile.getEntry(fileName);
if(entry == null)
{
throw new FileNotFoundException("cannot find file: " + fileName + " in archive: " + zipFile.getName());
}
zipStream = zipFile.getInputStream(entry);
fileStream = null;
try
{
final byte[] buf;
int i;
fileStream = new FileOutputStream(tempFile);
buf = new byte[1024];
i = 0;
while((i = zipStream.read(buf)) != -1)
{
fileStream.write(buf, 0, i);
}
}
finally
{
close(zipStream);
close(fileStream);
}
return (tempFile.toURI());
}
private static void close(final Closeable stream)
{
if(stream != null)
{
try
{
stream.close();
}
catch(final IOException ex)
{
ex.printStackTrace();
}
}
}
}
他のヒント
オペレーティング システムは .jar ファイルを気にせず、認識しないため、.jar ファイルを解凍する必要があります。 .exe
ファイルを実行する前に、一時的な場所に保存します。
//gets program.exe from inside the JAR file as an input stream
InputStream is = getClass().getResource("program.exe").openStream();
//sets the output stream to a system folder
OutputStream os = new FileOutputStream("program.exe");
//2048 here is just my preference
byte[] b = new byte[2048];
int length;
while ((length = is.read(b)) != -1) {
os.write(b, 0, length);
}
is.close();
os.close();
他のユーザーが質問に正しく答えている間に、抽出して実行し、その後クリーンアップします。考慮すべきもう 1 つの点は、完全にネイティブになることです。
すでにネイティブ バイナリを使用して特定のタスクを実行しています。アプリケーションをインストールするネイティブ インストーラーを作成し、バイナリを OS 固有の場所 (Win32 のプログラム ファイル) にインストールし、適切なショートカットを作成することもできます。
こうすることで、アプリケーションがよりネイティブに感じられるようになり、この事実を回避するためにコードを作成したり管理したりする必要がなくなることを意味します。現時点では、Jar はクロスプラットフォームのコードのように見えます (Jar はどこでも実行できますよね?) が、どこでも実行できるわけではないネイティブ バイナリがパックされています。これは矛盾しているように感じます。
インストーラーには、学ぶべき優れたチュートリアルとコード サンプルが多数ある Nullsoft Installation System (NSIS) をお勧めします。
使用
getClass().getResource(what).openStream()
そしてディスク内の別のファイルにコピーします。
Runtime.exec() を使用して exe を起動する簡単な Java プログラムを作成できます。次に、jar の「Main-Class」属性をそのランチャー クラスに設定できます。その後、ユーザーが jar を実行すると、exe が実行されます。