簡體   English   中英

運行打包在 jar 文件中的 exe

[英]Run exe which is packaged inside jar file

我正在通過我的 java 程序執行一個 exe。 路徑是用 Java 硬編碼的。

我已經將我的 exe 打包在 jar 中。

但是我卡住了,因為我在 Java 文件中硬編碼了路徑名,所以我無法將我的 jar 作為獨立程序執行。

打包此類 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 文件,因此您必須在執行之前將.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();

在其他用戶正確回答問題的同時,提取並運行然后清理。 要考慮的另一點是完全本地化。

您已經在使用本機二進制文件來完成特定任務。 為什么不創建一個本地安裝程序來安裝您的應用程序,並將二進制文件安裝到操作系統特定位置(Win32 上的程序文件)並創建合適的快捷方式。

通過這種方式,您的應用程序會感覺更原生,這意味着您無需編寫或管理代碼來解決這個問題。 目前,Jar 看起來像一段跨平台的代碼(Jar 可以在任何地方運行?)但打包了一個不會在任何地方運行的本機二進制文件。 這感覺很矛盾。

對於安裝人員,我可以推薦 Nullsoft 安裝系統 (NSIS),因為他們有許多優秀的教程和代碼示例可供學習。

getClass().getResource(what).openStream()

並復制到磁盤中的另一個文件。

您可以編寫一個簡單的 java 程序來使用 Runtime.exec() 啟動 exe。 然后,您可以將 jar 的“Main-Class”屬性設置為該啟動器類。 然后用戶可以運行您的 jar,它會運行 exe。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM