2010-07-30 6 views
51

Ich möchte eine XML-Datei lesen, die sich in einem der in meinem Klassenpfad enthaltenen jar befindet. Wie kann ich jede Datei lesen, die in der jar enthalten ist?Wie liest man eine Datei von jar in Java?

+0

siehe http://StackOverflow.com/Questions/16842306 – yegor256

+0

Wenn Sie Dateien aus einem Verzeichnis in jar mit beliebigen Nummern für Dateien lesen möchten, finden Sie unter [StackOverflow-Link] (https://StackOverflow.com/Questions/26185137/) spring-boot-resource-nicht-gefunden-wenn-using-executable-jar/39818817 # 39818817) –

Antwort

102

Wenn Sie diese Datei aus Ihrer Anwendungsnutzung zu lesen:

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

Der Weg beginnt mit „/“, aber das ist nicht der Pfad in Ihrem Dateisystem, aber in Ihrem Classpath. Wenn sich Ihre Datei im Klassenpfad "org.xml" befindet und den Namen myxml.xml trägt, sieht Ihr Pfad wie "/org/xml/myxml.xml" aus.

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

Ich hoffe, dass hilft.

+17

+1 für die Erklärung, warum die führende "/" notwendig ist. –

46

Ah, das ist eines meiner Lieblingsfächer. Es gibt im Wesentlichen zwei Möglichkeiten, wie Sie eine Ressource durch den Classpath laden können:

Class.getResourceAsStream(resource) 

und

ClassLoader.getResourceAsStream(resource) 

(es gibt auch andere Möglichkeiten, die eine URL für die Ressource in ähnlicher Weise beinhalten bekommen, dann eine Verbindung zu ihm öffnen, aber das sind die beiden direkten Wege).

Die erste Methode delegiert tatsächlich an die zweite, nachdem der Ressourcenname fehlgeschlagen ist. Es gibt im Wesentlichen zwei Arten von Ressourcennamen: absolut (z. B. "/ Pfad/zu/Ressource/Ressource") und relativ (z. B. "Ressource"). Absolute Pfade beginnen mit "/".

Hier ist ein Beispiel, das veranschaulichen sollte. Betrachten Sie eine Klasse com.example.A. Berücksichtigen Sie zwei Ressourcen, eine unter/com/example/nested, die andere unter/top im Klassenpfad. Das folgende Programm zeigt neun Möglichkeiten, 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 aus dem Programm:

 
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 Dinge tun, was man erwarten würde. Fall 3 schlägt fehl, weil die Klassenrelativierung in Bezug auf die Klasse erfolgt, also "oben" bedeutet "/ com/example/top", aber "/ top" bedeutet, was es sagt.

Fall-5 schlägt fehl, weil die relative Auflösung des Klassenladeprogramms in Bezug auf den Klassenlader ist. Aber auch Case-6 schlägt unerwartet fehl: Man könnte erwarten, dass "/ com/example/nested" korrekt aufgelöst wird. Um über den Klassenlader auf eine verschachtelte Ressource zuzugreifen, müssen Sie Case-7 verwenden, d. H. Der verschachtelte Pfad ist relativ zum Stamm des Klassenladeprogramms. Ebenso scheitert Fall-9, aber Fall-8 besteht. Denken Sie daran,

: für java.lang.Class, getResourceAsStream() delegiert an den Klassenlader:

 
    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); 
    } 

so ist es das Verhalten von ResolveName(), die wichtig ist.

Da das Verhalten des Klassenladeprogramms, das die Klasse geladen hat, im Wesentlichen getResourceAsStream() steuert und der Klassenlader häufig ein benutzerdefiniertes Ladeprogramm ist, sind die Regeln zum Laden von Ressourcen möglicherweise noch komplexer. z.B.für Web-Anwendungen, laden von WEB-INF/classes oder WEB-INF/lib im Kontext der Web-Anwendung, nicht aber von anderen Web-Anwendungen, die isoliert sind. Auch delegierte Klassenladeprogramme delegieren an Eltern, so dass duplizierte Ressourcen im Klassenpfad unter Verwendung dieses Mechanismus möglicherweise nicht zugänglich sind.

+0

Dies ist im Wesentlichen die gleiche Antwort, die ich gab, aber in viel erklärt mehr Details +1 – Mnementh

+0

Hier ist die resolveName-Methode, die erwähnt wurde: https://gist.github.com/briangordon/5374626 –

2

Ein JAR ist im Grunde eine ZIP-Datei, also behandeln Sie es so. Im Folgenden finden Sie ein Beispiel, wie Sie eine Datei aus einer WAR-Datei extrahieren (auch als ZIP-Datei behandeln) und den Inhalt der Zeichenfolge ausgeben können. Für Binärdateien müssen Sie den Extraktionsprozess modifizieren, 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 habe ich Apache Commons I/O bin mit und wenn Sie hier Maven verwenden, ist die Abhängigkeit:

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

prüfen zuerst die 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 
0

Nur der Vollständigkeit halber hat es eine question auf der Jython Mailingliste vor kurzem, in denen eine der Antworten auf diesen Thread bezeichnet.

Die Frage war, wie ein Python-Skript aufrufen, die in einer JAR-Datei aus Jython, die vorgeschlagene Antwort enthalten ist, ist wie folgt (mit „Input“, wie er in einer der Antworten oben erklärt:

PythonInterpreter.execfile(InputStream) 
Verwandte Themen