繁体   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