2016-06-19 11 views
2

Mein Code wird in einer JAR-Datei ausgeführt, und ich muss den vollständigen Pfad dieser Datei abrufen. Zum Beispiel heißt meine JAR example.jar und befindet sich unter D: \ example \ Also muss ich "D: \ example \ example.jar" durch Code in diesem Jar erhalten. Ich habe viele Methoden versucht, um diesen Pfad zu bekommen, aber keiner von ihnen hat richtig funktioniert.Wenn Sie den Pfad einer laufenden JAR-Datei abrufen, wird "rsrc: ./" zurückgegeben.

Einer von ihnen ist

getClass().getProtectionDomain().getCodeSource().getLocation().toURI().getPath() 

Viele Leute sagen, dass dies für sie funktioniert, aber es gibt „rsrc: ./“ für mich.

Ich habe danach gesucht, und ich bemerkte, dass mein MANIFEST.MF diese enthält:

Manifest-Version: 1.0 
Rsrc-Class-Path: ./ 
Class-Path: . 
Rsrc-Main-Class: Example 
Main-Class: org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader 

Ich weiß nicht, was das bedeutet, aber wenn ich entfernen, dass Rsrc Sachen und ersetzen damit die anderen Dinge Es sagt, das Glas ist kaputt. Ich denke, das ist der Grund, warum es nicht funktioniert. Weiß jemand, was das bedeutet?

PS: Ich verwende meine JAR mit einer BAT-Datei.

+1

Warum möchten Sie den Pfad der JAR? – SJuan76

+1

'getPath()' * * konvertiert einen URI nicht in eine Datei. Selbst wenn es sich um eine Datei: URI handelt, kann der Pfadbereich Prozent-Escapes enthalten, so dass getPath() schließlich eine Zeichenfolge zurückgibt, die kein gültiger Dateiname ist. Der richtige Weg, um einen URI in einen Dateinamen umzuwandeln, ist 'Paths.get (uri)', aber er funktioniert nur mit Datei: URIs. Nichtsdestoweniger kann und sollte mit Class.getResource oder ClassLoader.getResource verfahren werden. – VGR

+0

Sie können einen Pfad zum Jar selbst erhalten, aber es macht keinen Sinn, über einen Dateipfad zu einer Datei im Jar zu sprechen. – MeBigFatGuy

Antwort

0

Ich habe gerade einen neuen Arbeitsbereich erstellt und jedes Projekt hinein bewegt und alles funktioniert jetzt, ich denke, es ist ein Bug oder etwas war ... Vielen Dank für Ihre Hilfe!

0

Basierend auf Ihren Kommentaren scheint Ihre eigentliche Frage darin zu bestehen, wie Sie Dateien aus Ihrer .jar-Anwendung kopieren können. Sie können, dass wie diese mit etwas tun:

String jarEntry = "/files/data.txt"; 
Path destination = Paths.get(
    System.getProperty("user.home"), "Downloads", "data.txt"); 

try (InputStream stream = getClass().getResourceAsStream(jarEntry)) { 
    Files.copy(stream, destination); 
} 

Class.getResource und Class.getResourceAsStream Lesen von Daten aus dem Classpath, in der Regel als ein Eintrag in einer .jar-Datei, die auf dem Classpath ist, wie Sie Ihre eigene Anwendung. JAR-Datei.

Eine in den Klassenpfad eingebettete Datei wird normalerweise als Anwendungsressource oder einfach nur "Ressource" bezeichnet. Ressourcen werden immer mit dem Schrägstrich (/) als Verzeichnistrennzeichen auf allen Plattformen, auch Windows, angegeben.

Wenn Sie nicht sicher sind, welche Zeichenfolge an getResource oder getResourceAsStream übergeben werden soll, untersuchen Sie den Inhalt Ihrer JAR-Datei.

+0

Ich habe eine funktionierende Methode, um diese Ordner und Dateien zu kopieren, ich brauche nur den Pfad meiner JAR-Datei, um ihre Einträge auszulesen. Ich kann Ihre Methode nicht verwenden, weil zu viele Dateien vorhanden sind, um ihre Pfade manuell einzugeben. – Doenerstyle

+0

Warum öffnen Sie kein Terminalfenster oder Befehlsfenster, geben Sie einen Befehl wie 'dir/b' (in Windows) oder' ls -1' (andere Betriebssysteme) ein, kopieren Sie die Ausgabe und fügen Sie sie in Ihren Code ein als eine Reihe von Strings? Sie können auch 'jar tf' in Ihrer .jar-Datei nach dem Erstellen ausführen. – VGR

0
package com.example; 

import java.io.BufferedInputStream; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.IOException; 
import java.net.URL; 
import java.util.jar.JarEntry; 
import java.util.jar.JarInputStream; 

public class HomeJar { 

    public static void main(String[] args) throws IOException { 

     URL u = HomeJar.class.getProtectionDomain().getCodeSource().getLocation(); 

     File f = new File(u.getPath().toString()); 

     if (!f.isFile()) { 
      throw new RuntimeException("'" + u + "' isn't a jar"); 
     } 

     try (JarInputStream jis = new JarInputStream(new BufferedInputStream(new FileInputStream(f)))) { 
      JarEntry je = jis.getNextJarEntry(); 
      while (je != null) { 
       System.out.println(je.getName()); 
       je = jis.getNextJarEntry(); 
      } 
     } 
    } 

} 
+0

Wenn ich diese Klasse ausführen, wird eine InvocationTargetException ausgelöst, die durch die RuntimeException verursacht wird. Außerdem heißt es: "" rsrc: ./ "ist kein Jar, also ist es das gleiche Problem, das ich habe. – Doenerstyle

+0

Was jdk benutzt du? – MeBigFatGuy

+0

8 Update 77 (64-bit) – Doenerstyle

3

Ich bin auch über dieses Problem gestolpert und lasse meine Untersuchungen hier für Leute die sich in Zukunft fragen was die rsrc bedeutet.

Ich benutze Eclipse Mars 1 und versuche, mein Projekt als ausführbare JAR zu exportieren. Dort kann ich die Bibliothek Behandlung wählen und entscheiden zwischen:

  1. Extract benötigten Bibliotheken in generierten JAR
  2. Package erforderlichen Bibliotheken in generierten JAR
  3. Kopieren erforderlichen Bibliotheken in einen Unterordner neben dem erzeugten JAR

die Linie getestet werden soll

System.out.println(MyClass.class.getProtectionDomain().getCodeSource().getLocation()); 

die JAR fil Der Name ist MyJar.jar (das auf den Desktop gestellt wird), der Name und der Ordner von Project ist MyProject.

Ergebnisse:

  1. file:/C:/Users/admin/Desktop/MyJar.jar
  2. rsrc:./
  3. file:/C:/Users/admin/Desktop/MyJar.jar
  4. < bedeutet in Eclipse läuft > file:/C:/Development/workspace/MyProject/target/classes/

Ich schrieb ein convinience Methode dafür:

public class SystemUtils { 

    /** 
    * Let no one instanciate this class. 
    */ 
    private SystemUtils() {} 

    /** 
    * If the current JVM was started from within a JAR file. 
    * @return <code>Boolean.TRUE</code> if it is, <code>Boolean.FALSE</code> if it is not, <code>null</code> if unknown. 
    */ 
    public static Boolean executedFromWithinJar() { 
     Boolean withinJar = null; 
     try { 
      String location = SystemUtils.class.getProtectionDomain().getCodeSource().getLocation().toString(); 
      if (location.startsWith("rsrc:") 
       || location.endsWith(".jar") && !new File(location.substring(location.indexOf(':') + 1)).isDirectory()) 
       withinJar = Boolean.TRUE; 
      else 
       withinJar = Boolean.FALSE; 
     } 
     catch (Exception ex) {/* value is still null */} 
     return withinJar; 
    } 

} 
+0

danke GreenThor, das löste mein Problem nach stundenlanger Suche. – dariusiv