So erhalten Sie einen Pfad zu einer Ressource in einer Java-JAR-Datei

Lesezeit: 7 Minuten

So erhalten Sie einen Pfad zu einer Ressource in einer
no_ripcord

Ich versuche, einen Pfad zu einer Ressource zu finden, aber ich hatte kein Glück.

Dies funktioniert (sowohl in IDE als auch mit JAR), aber auf diese Weise kann ich keinen Pfad zu einer Datei erhalten, sondern nur den Dateiinhalt:

ClassLoader classLoader = getClass().getClassLoader();
PrintInputStream(classLoader.getResourceAsStream("config/netclient.p"));

Wenn ich das mache:

ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource("config/netclient.p").getFile());

Das Ergebnis ist:
java.io.FileNotFoundException: file:/path/to/jarfile/bot.jar!/config/netclient.p (No such file or directory)

Gibt es eine Möglichkeit, einen Pfad zu einer Ressourcendatei zu erhalten?

  • Jawohl. Ich habe eine Klasse, mit der ich sowohl arbeiten möchte, einen Ordner auf der Außenseite (falls ich einige Parameter der Konfigurationsdatei ändern möchte) als auch ein JAR, das die Implementierungskonfigurationsdateien für den Benutzer verbirgt (wie eine verteilbare JAR an alle Leute).

    – no_ripcord

    2. Juni 2009 um 20:41 Uhr

  • Die Klasse erhält also nur einen PATH zu einer Datei (der Konfigurationsdatei).

    – no_ripcord

    2. Juni 2009 um 20:42 Uhr

  • Dann sollten Sie diese Klasse wahrscheinlich mit einem Eingabestrom befassen, den Sie von beiden Quellen erhalten können.

    – Karl Manaster

    2. Juni 2009 um 20:43 Uhr

  • Ja, ich weiß. Andersherum wäre es aber klarer und sauberer gewesen. Aber trotzdem thx.

    – no_ripcord

    2. Juni 2009 um 20:47 Uhr

  • Versuchen Sie, in dieser Frage so etwas wie Option 4 zu tun? stackoverflow.com/questions/775389/…

    – Ericsson

    2. Juni 2009 um 22:36 Uhr

Dies ist Absicht. Der Inhalt der “Datei” ist möglicherweise nicht als Datei verfügbar. Denken Sie daran, dass Sie es mit Klassen und Ressourcen zu tun haben, die Teil einer JAR-Datei oder einer anderen Art von Ressource sein können. Der Klassenlader muss der Ressource kein Dateihandle bereitstellen, zum Beispiel darf die JAR-Datei nicht in einzelne Dateien im Dateisystem expandiert worden sein.

Alles, was Sie tun können, indem Sie eine java.io.File abrufen, können Sie tun, indem Sie den Stream in eine temporäre Datei kopieren und dasselbe tun, wenn eine java.io.File unbedingt erforderlich ist.

  • Sie können ‘rsrc:’ hinzufügen, wenn Sie Ihre Ressource aufrufen, um sie zu öffnen. like new File(“rsrc:filename.txt”) lädt dies filename.txt, das in das Stammverzeichnis Ihrer JAR-Datei gepackt ist

    – gips

    16. Juni 2016 um 18:45 Uhr


So erhalten Sie einen Pfad zu einer Ressource in einer
Tombart

Beachten Sie beim Laden einer Ressource unbedingt den Unterschied zwischen:

getClass().getClassLoader().getResource("com/myorg/foo.jpg") //relative path

und

getClass().getResource("/com/myorg/foo.jpg")); //note the slash at the beginning

Ich denke, diese Verwirrung verursacht die meisten Probleme beim Laden einer Ressource.


Auch wenn Sie ein Bild laden, ist es einfacher zu verwenden getResourceAsStream():

BufferedImage image = ImageIO.read(getClass().getResourceAsStream("/com/myorg/foo.jpg"));

Wenn Sie wirklich eine (Nicht-Bild-)Datei aus einem JAR-Archiv laden müssen, können Sie Folgendes versuchen:

File file = null;
String resource = "/com/myorg/foo.xml";
URL res = getClass().getResource(resource);
if (res.getProtocol().equals("jar")) {
    try {
        InputStream input = getClass().getResourceAsStream(resource);
        file = File.createTempFile("tempfile", ".tmp");
        OutputStream out = new FileOutputStream(file);
        int read;
        byte[] bytes = new byte[1024];

        while ((read = input.read(bytes)) != -1) {
            out.write(bytes, 0, read);
        }
        out.close();
        file.deleteOnExit();
    } catch (IOException ex) {
        Exceptions.printStackTrace(ex);
    }
} else {
    //this will probably work in your IDE, but not from a JAR
    file = new File(res.getFile());
}

if (file != null && !file.exists()) {
    throw new RuntimeException("Error: File " + file + " not found!");
}

  • +1 Das hat bei mir funktioniert. Stellen Sie sicher, dass Sie die Dateien, die Sie einlesen möchten, in der ablegen bin Ordner und gehen Sie in das Verzeichnis der Klasse, die in den Ressourcen geladen wird, bevor Sie den Pfad `/com/myorg/filename.ext’ verwenden.

    – rayryeng

    25. April 2014 um 16:58 Uhr

  • +1 Dies funktioniert auch für mich … Ich verstehe, dass mit diesem Ansatz einige Sicherheitsrisiken verbunden sein können, daher müssen sich Anwendungsbesitzer dessen bewusst sein.

    – LucasA

    27. Oktober 2014 um 13:39 Uhr

  • könnten Sie diese Aussage verdeutlichen “Es ist immer besser, eine Ressource mit getResourceAsStream() zu laden”? Wie kann das Problem gelöst werden?

    – Lukas S.

    2. November 2015 um 16:26 Uhr

  • @Lucas. Das war nur für den Fall von Bildern gedacht, tut mir leid, es war nicht sehr klar. Der Ansatz sollte plattformunabhängig sein, obwohl es ein bisschen hacky ist.

    – Tombart

    3. November 2015 um 16:11 Uhr

  • @LucasA Könnten Sie die von Ihnen erwähnten Risiken erläutern?

    – ZX9

    26. Januar 2016 um 18:24 Uhr

1646318231 690 So erhalten Sie einen Pfad zu einer Ressource in einer
Manojkumar Khotele

Die einzeilige Antwort lautet –

String path = this.getClass().getClassLoader().getResource(<resourceFileName>).toExternalForm()

Grundsätzlich getResource Methode gibt die URL an. Aus dieser URL können Sie per Aufruf den Pfad extrahieren toExternalForm().

  • Beim Ausführen aus meiner Umgebung (IntelliJ) erzeugt dies eine einfache Datei-URL, die in allen Fällen funktioniert. Wenn ich jedoch von der JAR-Datei selbst aus laufe, erhalte ich einen URI ähnlich wie jar:file:/path/to/jar/jarname.jar!/file_in_jar.mp4. Nicht alles kann einen URI verwenden, der mit jar beginnt. Ein typisches Beispiel sind JavaFX-Medien.

    – Noah Ternullo

    17. Dezember 2014 um 1:01 Uhr


  • Diese Antwort gefällt mir am besten. Zugegeben, in den meisten Fällen ist es möglicherweise vorzuziehen, den InputStream einfach in die Ressource zu packen, wenn er sich in einer JAR-Datei befindet, aber wenn Sie aus irgendeinem Grund den Pfad wirklich benötigen, funktioniert dies. Ich brauchte den Pfad, um ihn einem Objekt eines Drittanbieters zu geben. So danke!

    – Mario

    21. Juni 2016 um 15:36 Uhr

  • Die obige Lösung funktioniert nicht in der IDE, in Intellijit fügt hinzu file:/ zu path , was in jar funktioniert, aber nicht in IDE

    – Tayab Hussain

    13. Januar 2019 um 11:25 Uhr

  • Ihre Antwort löste ein Problem, das ich seit mindestens 2 Tagen zu lösen versuchte. TYVM!!

    – Jonathan

    9. November 2019 um 19:30 Uhr


Ich habe eine Weile mit diesem Problem herumgespielt, weil keine Lösung, die ich gefunden habe, tatsächlich funktioniert hat, seltsamerweise! Das Arbeitsverzeichnis ist häufig nicht das Verzeichnis der JAR-Datei, insbesondere wenn eine JAR-Datei (oder ein anderes Programm) über das Startmenü unter Windows ausgeführt wird. Hier ist also, was ich getan habe, und es funktioniert für .class-Dateien, die von außerhalb eines JAR ausgeführt werden, genauso gut wie für ein JAR. (Ich habe es nur unter Windows 7 getestet.)

try {
    //Attempt to get the path of the actual JAR file, because the working directory is frequently not where the file is.
    //Example: file:/D:/all/Java/TitanWaterworks/TitanWaterworks-en.jar!/TitanWaterworks.class
    //Another example: /D:/all/Java/TitanWaterworks/TitanWaterworks.class
    PROGRAM_DIRECTORY = getClass().getClassLoader().getResource("TitanWaterworks.class").getPath(); // Gets the path of the class or jar.

    //Find the last ! and cut it off at that location. If this isn't being run from a jar, there is no !, so it'll cause an exception, which is fine.
    try {
        PROGRAM_DIRECTORY = PROGRAM_DIRECTORY.substring(0, PROGRAM_DIRECTORY.lastIndexOf('!'));
    } catch (Exception e) { }

    //Find the last / and cut it off at that location.
    PROGRAM_DIRECTORY = PROGRAM_DIRECTORY.substring(0, PROGRAM_DIRECTORY.lastIndexOf("https://stackoverflow.com/") + 1);
    //If it starts with /, cut it off.
    if (PROGRAM_DIRECTORY.startsWith("https://stackoverflow.com/")) PROGRAM_DIRECTORY = PROGRAM_DIRECTORY.substring(1, PROGRAM_DIRECTORY.length());
    //If it starts with file:/, cut that off, too.
    if (PROGRAM_DIRECTORY.startsWith("file:/")) PROGRAM_DIRECTORY = PROGRAM_DIRECTORY.substring(6, PROGRAM_DIRECTORY.length());
} catch (Exception e) {
    PROGRAM_DIRECTORY = ""; //Current working directory instead.
}

wenn netclient.p in einer JAR-Datei befindet, hat sie keinen Pfad, da sich diese Datei in einer anderen Datei befindet. In diesem Fall ist der beste Weg, den Sie haben können, wirklich file:/path/to/jarfile/bot.jar!/config/netclient.p.

  • Wenn ich versuche, eine URL dieses Formats (…bot.jar!/config/…) in URI zu konvertieren, heißt es, dass der Pfad nicht hierarchisch ist.

    – gEdringer

    6. Juni 2018 um 10:12 Uhr

So erhalten Sie einen Pfad zu einer Ressource in einer
spottedmahn

Dies ist derselbe Code von Benutzer Tombart mit Stream Flush und Close, um eine unvollständige Kopie des temporären Dateiinhalts aus der JAR-Ressource zu vermeiden und eindeutige temporäre Dateinamen zu haben.

File file = null;
String resource = "/view/Trial_main.html" ;
URL res = getClass().getResource(resource);
if (res.toString().startsWith("jar:")) {
    try {
        InputStream input = getClass().getResourceAsStream(resource);
        file = File.createTempFile(new Date().getTime()+"", ".html");
        OutputStream out = new FileOutputStream(file);
        int read;
        byte[] bytes = new byte[1024];

        while ((read = input.read(bytes)) != -1) {
            out.write(bytes, 0, read);
        }
        out.flush();
        out.close();
        input.close();
        file.deleteOnExit();
    } catch (IOException ex) {
        ex.printStackTrace();
    }
} else {
    //this will probably work in your IDE, but not from a JAR
    file = new File(res.getFile());
}
         

  • Wenn ich versuche, eine URL dieses Formats (…bot.jar!/config/…) in URI zu konvertieren, heißt es, dass der Pfad nicht hierarchisch ist.

    – gEdringer

    6. Juni 2018 um 10:12 Uhr

Behalten Sie den Umschaltzustand des Menus mit JQuery bei
RevanthKrishnaKumar V.

Sie müssen den Pfad in der JAR-Datei verstehen.
Einfach relativ darauf beziehen. Wenn Sie also eine Datei (myfile.txt) haben, die sich in foo.jar unter der befindet \src\main\resources Verzeichnis (Maven-Stil). Sie würden sich darauf beziehen wie:

src/main/resources/myfile.txt

Wenn Sie Ihr Glas mit entleeren jar -tvf myjar.jar Sie sehen die Ausgabe und den relativen Pfad in der JAR-Datei und verwenden die FORWARD SLASES.

  • Sie müssen tatsächlich Schrägstriche verwenden, sogar unter Windows. Das bedeutet, dass Sie nicht verwenden können File.separator.

    – Str

    4. April 2016 um 8:31 Uhr

924390cookie-checkSo erhalten Sie einen Pfad zu einer Ressource in einer Java-JAR-Datei

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy