2009-03-01 145 views
18

我通過我的java程序執行exe文件。 該路徑在java中被硬編碼。運行在jar裏面的exe文件

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

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

包裝這種罐子的任何提示,即有一個EXE裏面,並能夠運行它作爲一個獨立的程序?

感謝, Krisp

回答

30

奇怪的是我今天早上寫類似的代碼...感謝您把我推來獲取:-)

做這將提取.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(); 
      } 
     } 
    } 
} 
11

操作系統不關心或瞭解.jar文件,所以你必須給.exe文件解壓到一些臨時位置在執行之前。

+0

我使用D.Snap描述的方法從資源文件複製到項目的根目錄下,我現在指的是像這樣的文件: 「文件文件=新的文件(」 your.exe」 );」。 因此,您可以打開文件以便從resources目錄(如果使用maven項目)寫入根目錄,如下所示: 「InputStream is = getClass()。getResource(」your.exe「)。openStream();」 – hipokito 2018-03-06 20:04:03

-5

你可以編寫一個簡單的java程序來使用Runtime.exec()啓動exe文件。然後,您可以將jar的「Main-Class」屬性設置爲啓動器類。用戶然後可以運行你的jar,它會運行該exe文件。

+0

在這種情況下,我將需要在java代碼中對exe路徑進行硬編碼。我想讓它變得輕便。 – krisp 2009-03-01 17:44:03

+0

@Krisp。不對。你可以使用Class/ClassLoader.getResource()在jar中找到一個相對路徑 – Kevin 2009-03-01 17:49:17

3

雖然其他用戶已經正確地回答了這個問題,提取物,然後運行清理。還有一點需要考慮的是完全原生的。

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

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

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

2

使用

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

,並複製到磁盤的另一個文件。

3
//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();