2013-03-12 15 views
12

Sto cercando di ottenere la posizione da cui viene eseguito un file JAR eseguibile. Ho provato a fareOttieni la posizione del file JAR

try { 
    String path = new java.io.File(".").getCanonicalPath(); 
} catch (IOException e) { 
    e.printStackTrace(); 
} 

Ma che restituisce:

C:\Users\Kevin\Desktop/server/Server 

mentre il file JAR si trova a

C:\Users\Kevin\Desktop 

Ho anche provato a fare

return new file(Server.class.getProtectionDomain().getCodeSource().getLocation().getPath()); 

Ma che restituisce :

C:\Users\Kevin\Desktop\server.jar/server/Server 

Quindi, in linea di massima, desidero il percorso del file JAR senza il nome file e non il ClassPath.

Qualsiasi modo per farlo?

+1

Questa potrebbe essere utile, discussione permeabile. http://stackoverflow.com/questions/320542/how-to-get-the-path-of-a-running-jar-file // Henrik – Hiny

+0

La specifica è incompleta. Cosa dovrebbe essere fatto se * non * stai correndo da un JAR? Cosa succede se il JAR vive in qualche rete? – Ingo

+0

Beh, il fatto è che sto cercando di creare una directory contenente i file e che deve essere sul mio desktop o ovunque io stia eseguendo il JAR. Se lo eseguo in modalità di debug all'interno di Eclipse, crea i file nella cartella bin/server. – Snakybo

risposta

16

Aggiornamento

Poiché non funziona in alcuni casi di test, aggiornerò la risposta.

Il modo corretto per fare questo dovrebbe essere con ClassLoader:

File jarDir = new File(ClassLoader.getSystemClassLoader().getResource(".").getPath()); 
System.out.println(jarDir.getAbsolutePath()); 

testati su vari percorsi di classe, l'uscita è stata corretta.


Vecchio risposta

Questo dovrebbe funzionare

File f = new File(System.getProperty("java.class.path")); 
File dir = f.getAbsoluteFile().getParentFile(); 
String path = dir.toString(); 

Funziona per me, il mio programma è in:

C:\Users\User01\Documents\app1\dist\JavaApplication1.jar 

e restituisce

C:\Users\User01\Documents\app1\dist 
+5

Funziona solo fino a quando classpath contiene una sola voce. – Ingo

+0

@BackSlash hai mai provato il codice sopra sul sistema linux/unix funziona perfettamente? – dbw

+0

@Ingo "classpath contiene solo una voce" cosa significa in realtà ... ?? – dbw

-1

Se si conosce

file(Server.class.getProtectionDomain().getCodeSource().getLocation().getPath()); 

rendimenti

C:\Users\Kevin\Desktop\server.jar/server/Server 

E sai che il tuo nome è Jar server.jar o per materia qualsiasi file .jar, la vostra intenzione è quello di ottenere C: \ Users \ Kevin \ Desktop, il modo più semplice è di manipolare le stringhe.

Con l'uscita recuperate, tokenize la stringa in base a File.separator e costruire il percorso (concatenando le corde con File.separator in mezzo) fino ad ottenere un token che contiene .jar

+0

Sì, ma cosa succede se gli utenti decidono di cambiare il nome del JAR? – Snakybo

+0

Non dovresti cercare con il nome del file jar hard codificato, idealmente dopo aver recuperato il token, dovresti controllare se quel token.contains (.jar), questo funzionerà come potrebbe essere il tuo nome file jar –

+0

No, non lo farà, per esempio se è stato rinominato ZIP – Ingo

15

Con la presente la mia versione di calcolare la directory jar

/** 
* Compute the absolute file path to the jar file. 
* The framework is based on http://stackoverflow.com/a/12733172/1614775 
* But that gets it right for only one of the four cases. 
* 
* @param aclass A class residing in the required jar. 
* 
* @return A File object for the directory in which the jar file resides. 
* During testing with NetBeans, the result is ./build/classes/, 
* which is the directory containing what will be in the jar. 
*/ 
public static File getJarDir(Class aclass) { 
    URL url; 
    String extURL;  // url.toExternalForm(); 

    // get an url 
    try { 
     url = aclass.getProtectionDomain().getCodeSource().getLocation(); 
      // url is in one of two forms 
      //  ./build/classes/ NetBeans test 
      //  jardir/JarName.jar froma jar 
    } catch (SecurityException ex) { 
     url = aclass.getResource(aclass.getSimpleName() + ".class"); 
     // url is in one of two forms, both ending "/com/physpics/tools/ui/PropNode.class" 
     //   file:/U:/Fred/java/Tools/UI/build/classes 
     //   jar:file:/U:/Fred/java/Tools/UI/dist/UI.jar! 
    } 

    // convert to external form 
    extURL = url.toExternalForm(); 

    // prune for various cases 
    if (extURL.endsWith(".jar")) // from getCodeSource 
     extURL = extURL.substring(0, extURL.lastIndexOf("/")); 
    else { // from getResource 
     String suffix = "/"+(aclass.getName()).replace(".", "/")+".class"; 
     extURL = extURL.replace(suffix, ""); 
     if (extURL.startsWith("jar:") && extURL.endsWith(".jar!")) 
      extURL = extURL.substring(4, extURL.lastIndexOf("/")); 
    } 

    // convert back to url 
    try { 
     url = new URL(extURL); 
    } catch (MalformedURLException mux) { 
     // leave url unchanged; probably does not happen 
    } 

    // convert url to File 
    try { 
     return new File(url.toURI()); 
    } catch(URISyntaxException ex) { 
     return new File(url.getPath()); 
    } 
} 
0

ho dovuto fare un giro molto prima ho finalmente trovato una soluzione di lavoro.
È possibile che jarLocation sia fornito con un prefisso come file:\ o jar:file\, che può essere rimosso utilizzando String#substring().

URL jarLocationUrl = MyClass.class.getProtectionDomain().getCodeSource().getLocation(); 
String jarLocation = new File(jarLocationUrl.toString()).getParent(); 
Problemi correlati