30

我正在通过我的 java 程序执行一个 exe。路径是用 Java 硬编码的。

我已将我的 exe 打包在 jar 中。

但是我卡住了,因为我在 Java 文件中硬编码了路径名,所以我无法将我的 jar 作为独立程序执行。

打包此类 jar 的任何提示,即内部有一个 exe 并能够将其作为独立程序运行?

4

6 回答 6

37

这将提取.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();
            }
        }
    }
}
于 2009-03-01T18:05:13.650 回答
12

操作系统不关心或知道 .jar 文件,因此您必须.exe在执行之前将该文件解压缩到某个临时位置。

于 2009-03-01T17:33:51.027 回答
6
//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();
于 2016-04-04T12:13:25.317 回答
3

虽然其他用户已正确回答问题,但提取并运行然后清理。要考虑的另一点是完全原生化。

您已经在使用本机二进制文件来完成特定任务。为什么不创建一个本机安装程序来安装您的应用程序,并将二进制文件安装到操作系统特定位置(Win32 上的程序文件)并创建合适的快捷方式。

这样,您的应用程序会感觉更加原生,这意味着您无需编写或管理代码即可绕过这一事实。目前,Jar 看起来像一个跨平台的代码(Jar 可以在任何地方运行,对吗?),但它包含一个不会在任何地方运行的本机二进制文件。这感觉很矛盾。

对于安装人员,我可以推荐 Nullsoft 安装系统 (NSIS),因为他们有许多优秀的教程和代码示例可供学习。

于 2011-09-07T11:51:13.217 回答
2

采用

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

并复制到磁盘中的另一个文件。

于 2013-02-08T13:37:40.463 回答
-5

您可以编写一个简单的 java 程序来使用 Runtime.exec() 启动 exe。然后,您可以将 jar 的“Main-Class”属性设置为该启动器类。然后用户可以运行你的 jar,它会运行 exe。

于 2009-03-01T17:39:07.097 回答