Ich möchte eine XML-Datei lesen, die sich in einer der befindet jar
s in meinem Klassenpfad enthalten. Wie kann ich jede Datei lesen, die in der jar
?
Wie liest man eine Datei aus JAR in Java?
kandarp
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.
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 nested=java.io.BufferedInputStream@19821f 2: A.class /com/example/nested=java.io.BufferedInputStream@addbf1 3: A.class top=null 4: A.class /top=java.io.BufferedInputStream@42e816 5: cl nested=null 6: cl /com/example/nested=null 7: cl com/example/nested=java.io.BufferedInputStream@9304b1 8: cl top=java.io.BufferedInputStream@190d11 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)
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);
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