Ich lade eine Textdatei aus einem Paket in eine kompilierte JAR meines Java-Projekts. Die relevante Verzeichnisstruktur lautet wie folgt:
/src/initialization/Lifepaths.txt
Mein Code lädt eine Datei, indem er aufruft Class::getResourceAsStream
, um a zurückzugeben InputStream
.
public class Lifepaths {
public static void execute() {
System.out.println(Lifepaths.class.getClass().
getResourceAsStream("/initialization/Lifepaths.txt"));
}
private Lifepaths() {}
//This is temporary; will eventually be called from outside
public static void main(String[] args) {execute();}
}
Der Ausdruck wird immer gedruckt null
, egal was ich benutze. Ich bin mir nicht sicher, warum das oben genannte nicht funktionieren würde, also habe ich auch versucht:
"/src/initialization/Lifepaths.txt"
"initialization/Lifepaths.txt"
"Lifepaths.txt"
Keine dieser Arbeiten. Ich habe bisher zahlreiche Fragen zu diesem Thema gelesen , aber keine davon war hilfreich - normalerweise wird nur gesagt, dass Dateien über den Stammpfad geladen werden sollen, was ich bereits tue. Das, oder laden Sie einfach die Datei aus dem aktuellen Verzeichnis (nur laden ), was ich auch versucht habe. Die Datei wird an der entsprechenden Stelle mit dem entsprechenden Namen in die JAR kompiliert. filename
Wie löse ich das?
Lifepaths.class
. Davon abgesehen, warum lässtgetClassLoader()
es funktionieren? (AuchLifepaths.getClass()
? Es gibt keine solche statische Methode in Objekt ...getResource(String)
. Übrigens: Ich hatte immer Probleme, einen von beiden in einemstatic
Kontext zum Laufen zu bringen. Das Problem ist im Grunde, dass der erhaltene Klassenlader derjenige ist, der für J2SE-Klassen bestimmt ist. Sie müssen Zugriff auf die bekommen Kontext Class Loader , die für die Anwendung vorgesehen ist selbst.Antworten:
Lifepaths.class.getClass().getResourceAsStream(...)
Lädt Ressourcen mit dem System Class Loader. Dies schlägt offensichtlich fehl, da Ihre JARs nicht angezeigt werdenLifepaths.class.getResourceAsStream(...)
Lädt Ressourcen mit demselben Klassenladeprogramm, das die Lifepaths-Klasse geladen hat, und sollte Zugriff auf Ressourcen in Ihren JARs habenquelle
/
vor Ihrem Pfad ein hinzufügen, wenn sich Ihre Datei in einem anderen Verzeichnis befindet. zum Beispielinitialization/Lifepaths.txt
. Wenn der Pfad der Datei das ist dieselbe von yout Klasse (aber unter Ressourcen als Haupt dir) können Sie den Namen der Datei , ohne gerade auf/
. Wenn Ihre Klasse beispielsweise den folgenden Pfad hatsrc/main/java/paths/Lifepaths.java
, muss Ihre Datei diesen Pfad habensrc/main/resources/paths/Lifepaths.txt
.Die Regeln lauten wie folgt:
Und versuche:
anstatt
(Ich bin mir nicht sicher, ob es einen Unterschied macht, aber der erstere verwendet den richtigen ClassLoader / JAR, während ich bei dem letzteren nicht sicher bin.)
quelle
Es gibt also verschiedene Möglichkeiten, eine Ressource aus einem JAR abzurufen, und jede hat eine leicht unterschiedliche Syntax, bei der der Pfad anders angegeben werden muss.
Die beste Erklärung, die ich gesehen habe, ist dieser Artikel aus JavaWorld . Ich fasse hier zusammen, aber wenn Sie mehr wissen wollen, sollten Sie den Artikel lesen.
Methoden
1)
ClassLoader.getResourceAsStream()
.Format: "/" - getrennte Namen; kein führendes "/" (alle Namen sind absolut).
Beispiel:
this.getClass().getClassLoader().getResourceAsStream("some/pkg/resource.properties");
2)
Class.getResourceAsStream()
Format: "/" - getrennte Namen; führendes "/" zeigt absolute Namen an; Alle anderen Namen beziehen sich auf das Paket der Klasse
Beispiel:
this.getClass().getResourceAsStream("/some/pkg/resource.properties");
quelle
Verwenden Sie keine absoluten Pfade, sondern machen Sie sie relativ zum Ressourcenverzeichnis in Ihrem Projekt. Schneller und schmutziger Code, der den Inhalt von MyTest.txt aus dem Verzeichnis 'resources' anzeigt.
quelle
Vielleicht möchten Sie dies versuchen, um den Stream abzurufen, dh zuerst die URL abrufen und dann als Stream öffnen.
Ich hatte einmal eine ähnliche Frage: Das Lesen der txt-Datei aus dem Glas schlägt fehl, aber das Lesen des Bildes funktioniert
quelle
Es scheint ein Problem mit dem von Ihnen verwendeten ClassLoader zu geben. Verwenden Sie den contextClassLoader, um die Klasse zu laden. Dies ist unabhängig davon, ob es sich um eine statische / nicht statische Methode handelt
Thread.currentThread().getContextClassLoader().getResourceAsStream
......quelle
Ich befand mich in einem ähnlichen Problem. Da ich maven verwende, musste ich meine pom.xml so aktualisieren, dass sie Folgendes enthält:
Notieren Sie sich dort das Ressourcen-Tag, um anzugeben, wo sich dieser Ordner befindet. Wenn Sie verschachtelte Projekte haben (wie ich), möchten Sie möglicherweise Ressourcen aus anderen Bereichen abrufen, anstatt nur in dem Modul, in dem Sie arbeiten. Dies hilft, die Verwendung derselben Datei in jedem Repo zu reduzieren, wenn Sie ähnliche Konfigurationsdaten verwenden
quelle
Was für mich funktionierte, war das Hinzufügen der Datei unter
My Project/Java Resources/src
und dann zu verwendenIch musste diese Datei nicht explizit zum Pfad hinzufügen (das Hinzufügen zu
/src
macht das anscheinend)quelle
Ich weiß nicht, ob ich Hilfe brauche, aber in meinem Fall hatte ich meine Ressource im Ordner / src / und bekam diesen Fehler. Ich habe das Bild dann in den Ordner bin verschoben und das Problem behoben.
quelle
Stellen Sie sicher, dass sich Ihr Ressourcenverzeichnis (z. B. "src") in Ihrem Klassenpfad befindet (stellen Sie sicher, dass es sich in Eclipse um ein Quellverzeichnis in Ihrem Erstellungspfad handelt).
Stellen Sie sicher, dass clazz vom Hauptklassenlader geladen wird.
Verwenden Sie dann zum Laden von src / initialization / Lifepaths.txt
Warum:
clazz.getResourcesAsStream(foo)
schaut foo aus dem Klassenpfad von clazz nach , relativ zu dem Verzeichnis , in dem clazz lebt . Das führende "/" bewirkt, dass es aus dem Stammverzeichnis eines beliebigen Verzeichnisses im Klassenpfad von clazz geladen wird.Sofern Sie sich nicht in einem Container wie Tomcat befinden oder etwas direkt mit ClassLoaders tun, können Sie Ihren Eclipse- / Befehlszeilen-Klassenpfad einfach als den einzigen Classloader-Klassenpfad behandeln.
quelle
Der Standard-JVM-Klassenlader verwendet den übergeordneten Klassenlader, um zuerst Ressourcen zu laden: .
Lifepaths.class.getClass()
's Classloader istbootstrap classloader
, alsogetResourceAsStream
wird nur $ JAVA_HOME durchsucht, unabhängig vom angegebenen Benutzerclasspath
. Offensichtlich ist Lifepaths.txt nicht da.Lifepaths.class
's Classloader istsystem classpath classloader
, sogetResourceAsStream
wird die Suche benutzerdefiniertclasspath
und Lifepaths.txt ist da.Bei Verwendung
java.lang.Class#getResourceAsStream(String name)
wird ein Name, der nicht mit '/' beginnt ,package name
als Präfix hinzugefügt . Wenn Sie dies vermeiden möchten, verwenden Sie bittejava.lang.ClassLoader#getResourceAsStream
. Beispielsweise:quelle
Grob gesagt:
getClass().getResource("/")
~ =Thread.currentThread().getContextClassLoader().getResource(".")
Angenommen, Ihre Projektstruktur sieht wie folgt aus:
quelle
Wenn Sie Maven verwenden, stellen Sie sicher, dass Ihre Verpackung "jar" und nicht "pom" ist.
quelle
Was Sie wirklich brauchen, ist ein vollständiger absoluter Klassenpfad für die Datei. Versuchen Sie also, anstatt es zu erraten, den ROOT herauszufinden und verschieben Sie die Datei dann an einen besseren Ort, der auf einer <.war> -Dateistruktur basiert ...
quelle
Was für mich funktioniert hat, ist, dass ich die Datei unter platziert habe
und
quelle
@ Emracool ... Ich würde Ihnen eine Alternative vorschlagen. Da scheinen Sie zu versuchen, eine * .txt-Datei zu laden. Besser zu verwenden als
FileInputStream()
dieses nervigegetClass().getClassLoader().getResourceAsStream()
odergetClass().getResourceAsStream()
. Zumindest wird Ihr Code ordnungsgemäß ausgeführt.quelle