Wie liest man eine Datei aus JAR in Java?

Lesezeit: 6 Minuten

Wie liest man eine Datei aus JAR in Java
kandarp

Ich möchte eine XML-Datei lesen, die sich in einer der befindet jars in meinem Klassenpfad enthalten. Wie kann ich jede Datei lesen, die in der jar?

  • siehe stackoverflow.com/questions/16842306

    – jegor256

    30. Mai 2013 um 19:34 Uhr

  • Wenn Sie Dateien aus einem Verzeichnis in jar mit beliebigen Nummern für Dateien lesen möchten, siehe Stackoverflow-Link

    – Michael Hegner

    2. Oktober 2016 um 16:02 Uhr

1646316428 737 Wie liest man eine Datei aus JAR in Java
Menmenth

Wenn Sie diese Datei in Ihrer Anwendung lesen möchten, verwenden Sie:

InputStream input = getClass().getResourceAsStream("/classpath/to/my/file");

Der Pfad beginnt mit „https://stackoverflow.com/“, aber das ist nicht der Pfad in Ihrem Dateisystem, sondern in Ihrem Klassenpfad. Wenn sich Ihre Datei also im Klassenpfad “org.xml” befindet und myxml.xml heißt, sieht Ihr Pfad wie folgt aus: “/org/xml/myxml.xml”.

Der InputStream liest den Inhalt Ihrer Datei. Sie können es in einen Reader packen, wenn Sie möchten.

Ich hoffe das hilft.

Wie liest man eine Datei aus JAR in Java
Simontuffs

Ah, das ist eines meiner Lieblingsthemen. Es gibt im Wesentlichen zwei Möglichkeiten, wie Sie eine Ressource über den Klassenpfad laden können:

Class.getResourceAsStream(resource)

und

ClassLoader.getResourceAsStream(resource)

(Es gibt andere Möglichkeiten, auf ähnliche Weise eine URL für die Ressource zu erhalten und dann eine Verbindung zu ihr herzustellen, aber dies sind die beiden direkten Wege).

Die erste Methode delegiert tatsächlich an die zweite, nachdem der Ressourcenname verstümmelt wurde. Es gibt im Wesentlichen zwei Arten von Ressourcennamen: absolute (z. B. „/Pfad/zu/Ressource/Ressource“) und relative (z. B. „Ressource“). Absolute Pfade beginnen mit „https://stackoverflow.com/“.

Hier ist ein Beispiel, das veranschaulichen soll. Betrachten Sie eine Klasse com.example.A. Stellen Sie sich zwei Ressourcen vor, eine befindet sich unter /com/example/nested, die andere unter /top im Klassenpfad. Das folgende Programm zeigt neun Möglichkeiten, auf die beiden Ressourcen zuzugreifen:

package com.example;

public class A {

    public static void main(String args[]) {

        // Class.getResourceAsStream
        Object resource = A.class.getResourceAsStream("nested");
        System.out.println("1: A.class nested=" + resource);

        resource = A.class.getResourceAsStream("/com/example/nested");
        System.out.println("2: A.class /com/example/nested=" + resource);

        resource = A.class.getResourceAsStream("top");
        System.out.println("3: A.class top=" + resource);

        resource = A.class.getResourceAsStream("/top");
        System.out.println("4: A.class /top=" + resource);

        // ClassLoader.getResourceAsStream
        ClassLoader cl = A.class.getClassLoader();
        resource = cl.getResourceAsStream("nested");        
        System.out.println("5: cl nested=" + resource);

        resource = cl.getResourceAsStream("/com/example/nested");
        System.out.println("6: cl /com/example/nested=" + resource);
        resource = cl.getResourceAsStream("com/example/nested");
        System.out.println("7: cl com/example/nested=" + resource);

        resource = cl.getResourceAsStream("top");
        System.out.println("8: cl top=" + resource);

        resource = cl.getResourceAsStream("/top");
        System.out.println("9: cl /top=" + resource);
    }

}

Die Ausgabe des Programms ist:

1: A.class [email protected]
2: A.class /com/example/[email protected]
3: A.class top=null
4: A.class /[email protected]
5: cl nested=null
6: cl /com/example/nested=null
7: cl com/example/[email protected]
8: cl [email protected]
9: cl /top=null

Meistens tun die Dinge, was Sie erwarten würden. Fall-3 schlägt fehl, weil die klassenrelative Auflösung sich auf die Klasse bezieht, also bedeutet “top” “/com/example/top”, aber “/top” bedeutet, was es sagt.

Fall-5 schlägt fehl, weil die relative Auflösung des Klassenladers sich auf den Klassenlader bezieht. Aber unerwarteterweise schlägt Fall-6 auch fehl: Man könnte erwarten, dass “/com/example/nested” richtig aufgelöst wird. Um über den Klassenlader auf eine verschachtelte Ressource zuzugreifen, müssen Sie Case-7 verwenden, dh der verschachtelte Pfad ist relativ zum Stamm des Klassenladers. Ebenso schlägt Fall-9 fehl, aber Fall-8 besteht.

Denken Sie daran: Für java.lang.Class delegiert getResourceAsStream() an den Classloader:

     public InputStream getResourceAsStream(String name) {
        name = resolveName(name);
        ClassLoader cl = getClassLoader0();
        if (cl==null) {
            // A system class.
            return ClassLoader.getSystemResourceAsStream(name);
        }
        return cl.getResourceAsStream(name);
    }

Daher ist das Verhalten von resolveName() wichtig.

Da schließlich das Verhalten des Classloaders, der die Klasse geladen hat, getResourceAsStream() im Wesentlichen steuert, und der Classloader oft ein benutzerdefinierter Loader ist, können die Regeln zum Laden von Ressourcen sogar noch komplexer sein. zB für Web-Anwendungen, laden Sie von WEB-INF/classes oder WEB-INF/lib im Kontext der Web-Anwendung, aber nicht von anderen Web-Anwendungen, die isoliert sind. Außerdem delegieren gut erzogene Classloader an Eltern, sodass duplizierte Ressourcen im Klassenpfad unter Verwendung dieses Mechanismus möglicherweise nicht zugänglich sind.

  • Dies ist im Wesentlichen die gleiche Antwort, die ich gegeben habe, aber viel detaillierter erklärt. +1

    – Mnementh

    2. August 2010 um 10:52 Uhr

  • Hier ist die erwähnte Methode resolveName: gist.github.com/briangordon/5374626

    – Lappen

    12. April 2013 um 19:51 Uhr

Überprüfen Sie zuerst Ihren Klassenlader.

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

if (classLoader == null) {
    classLoader = Class.class.getClassLoader();
}

classLoader.getResourceAsStream("xmlFileNameInJarFile.xml");

// xml file location at xxx.jar
// + folder
// + folder
// xmlFileNameInJarFile.xml

Ein JAR ist im Grunde eine ZIP-Datei, also behandeln Sie es als solche. Unten finden Sie ein Beispiel, wie Sie eine Datei aus einer WAR-Datei extrahieren (auch als ZIP-Datei behandeln) und den Inhalt der Zeichenfolge ausgeben. Für Binärdateien müssen Sie den Extraktionsprozess ändern, aber dafür gibt es viele Beispiele.

public static void main(String args[]) {
    String relativeFilePath = "style/someCSSFile.css";
    String zipFilePath = "/someDirectory/someWarFile.war";
    String contents = readZipFile(zipFilePath,relativeFilePath);
    System.out.println(contents);
}

public static String readZipFile(String zipFilePath, String relativeFilePath) {
    try {
        ZipFile zipFile = new ZipFile(zipFilePath);
        Enumeration<? extends ZipEntry> e = zipFile.entries();

        while (e.hasMoreElements()) {
            ZipEntry entry = (ZipEntry) e.nextElement();
            // if the entry is not directory and matches relative file then extract it
            if (!entry.isDirectory() && entry.getName().equals(relativeFilePath)) {
                BufferedInputStream bis = new BufferedInputStream(
                        zipFile.getInputStream(entry));
                // Read the file
                    // With Apache Commons I/O
                 String fileContentsStr = IOUtils.toString(bis, "UTF-8");

                    // With Guava
                //String fileContentsStr = new String(ByteStreams.toByteArray(bis),Charsets.UTF_8);
                // close the input stream.
                bis.close();
                return fileContentsStr;
            } else {
                continue;
            }
        }
    } catch (IOException e) {
        logger.error("IOError :" + e);
        e.printStackTrace();
    }
    return null;
}

In diesem Beispiel verwende ich Apache Commons I/O und wenn Sie Maven verwenden, ist hier die Abhängigkeit:

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.4</version>
</dependency>

Nur der Vollständigkeit halber gab es kürzlich eine Frage auf der Jython-Mailingliste, wo sich eine der Antworten auf diesen Thread bezog.

Die Frage war, wie man ein Python-Skript, das in einer .jar-Datei enthalten ist, innerhalb von Jython aufruft. Die vorgeschlagene Antwort lautet wie folgt (mit “InputStream”, wie in einer der Antworten oben erklärt):

PythonInterpreter.execfile(InputStream)

Wie liest man eine Datei aus JAR in Java
Inan Cakil

Das funktioniert auch im Frühjahr

    ClassPathResource resource = new ClassPathResource("/file.txt", MainApplication.class); //resources folder
    InputStream inputStream = resource.getInputStream();

    File file = new File("file.txt");
    FileUtils.copyInputStreamToFile(inputStream, file);

924150cookie-checkWie liest man eine Datei aus JAR in Java?

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

Privacy policy