Ich habe diesen Code, der alle Dateien aus einem Verzeichnis liest.
File textFolder = new File("text_directory");
File [] texFiles = textFolder.listFiles( new FileFilter() {
public boolean accept( File file ) {
return file.getName().endsWith(".txt");
}
});
Es funktioniert großartig. Es füllt das Array mit allen Dateien, die mit ".txt" aus dem Verzeichnis "text_directory" enden.
Wie kann ich den Inhalt eines Verzeichnisses in einer ähnlichen Art und Weise lesen in einer JAR - Datei?
Was ich also wirklich tun möchte, ist, alle Bilder in meiner JAR-Datei aufzulisten, damit ich sie laden kann mit:
ImageIO.read(this.getClass().getResource("CompanyLogo.png"));
(Das funktioniert, weil das "CompanyLogo" "fest codiert" ist, aber die Anzahl der Bilder in der JAR-Datei zwischen 10 und 200 variabler Länge liegen kann.)
BEARBEITEN
Ich denke, mein Hauptproblem wäre: Woher weiß ich den Namen der JAR-Datei, in der meine Hauptklasse lebt?
Zugegeben, ich konnte es mit lesen java.util.Zip
.
Meine Struktur ist wie folgt:
Sie sind wie:
my.jar!/Main.class
my.jar!/Aux.class
my.jar!/Other.class
my.jar!/images/image01.png
my.jar!/images/image02a.png
my.jar!/images/imwge034.png
my.jar!/images/imagAe01q.png
my.jar!/META-INF/manifest
Im Moment kann ich zum Beispiel "images / image01.png" laden mit:
ImageIO.read(this.getClass().getResource("images/image01.png));
Aber nur weil ich den Dateinamen kenne, muss ich sie im Übrigen dynamisch laden.
Antworten:
Beachten Sie, dass Sie in Java 7 eine
FileSystem
Datei aus der JAR-Datei (zip) erstellen und diese dann mithilfe der NIO-Mechanismen zum Durchsuchen und Filtern von Verzeichnissen durchsuchen können. Dies würde es einfacher machen, Code zu schreiben, der JARs und "explodierte" Verzeichnisse verarbeitet.quelle
Code, der sowohl für IDE- als auch für JAR-Dateien funktioniert:
quelle
FileSystems.newFileSystem()
nimmt einMap<String, ?>
, also müssen Sie angeben,Collections.emptyMap()
dass es ein entsprechend typisiertes zurückgeben muss. Das funktioniert :Collections.<String, Object>emptyMap()
.fileSystem
!walk
Methode inFiles
ist nur in 1.8 verfügbar). Das einzige Problem ist, dass das RessourcenverzeichnisFiles.walk(myPath, 1)
nicht nur in den Dateien angezeigt wird . Ich denke, das erste Element kann einfach ignoriert werdenmyPath = fileSystem.getPath("/resources");
funktioniert bei mir nicht; es findet nichts. Es sollte in meinem Fall "Bilder" sein und das "Bilder" -Verzeichnis ist definitiv in meinem Glas enthalten!ericksons antwort funktionierte perfekt:
Hier ist der Arbeitscode.
Und ich habe gerade meine Lademethode daraus geändert:
Dazu:
quelle
Ich möchte die Antwort von acheron55 erweitern , da es sich aus mehreren Gründen um eine sehr unsichere Lösung handelt:
FileSystem
Objekt wird nicht geschlossen .FileSystem
Objekt bereits vorhanden ist.Dies ist eine etwas sicherere Lösung:
Es besteht keine wirkliche Notwendigkeit, über den Dateinamen zu synchronisieren. Man könnte einfach jedes Mal mit demselben Objekt synchronisieren (oder die Methode erstellen
synchronized
), es ist lediglich eine Optimierung.Ich würde sagen, dass dies immer noch eine problematische Lösung ist, da es möglicherweise andere Teile im Code gibt, die die
FileSystem
Schnittstelle über dieselben Dateien verwenden, und sie möglicherweise stören (sogar in einer einzelnen Thread-Anwendung).Außerdem wird nicht nach
null
s gesucht (z. B. nach)getClass().getResource()
.Diese spezielle Java NIO-Schnittstelle ist schrecklich, da sie eine nicht threadsichere globale / Singleton-Ressource einführt und ihre Dokumentation äußerst vage ist (viele Unbekannte aufgrund anbieterspezifischer Implementierungen). Die Ergebnisse können für andere
FileSystem
Anbieter (nicht JAR) variieren . Vielleicht gibt es einen guten Grund dafür; Ich weiß nicht, ich habe die Implementierungen nicht recherchiert.quelle
Angenommen, Ihr Projekt ist in einem Jar gepackt (nicht unbedingt wahr!), Können Sie ClassLoader.getResource () oder findResource () mit dem Klassennamen (gefolgt von .class) verwenden, um das Jar zu erhalten, das eine bestimmte Klasse enthält. Sie müssen den JAR-Namen von der URL analysieren, die zurückgegeben wird (nicht so schwierig), was ich als Übung für den Leser hinterlassen werde :-)
Stellen Sie sicher, dass Sie den Fall testen, in dem die Klasse nicht Teil eines Glases ist.
quelle
CodeSource
.Ich habe die Antwort von acheron55 auf Java 7 portiert und das
FileSystem
Objekt geschlossen . Dieser Code funktioniert in IDEs, in JAR-Dateien und in einem JAR in einem Krieg gegen Tomcat 7. Beachten Sie jedoch, dass es in einem Glas in einem Krieg gegen JBoss 7 nicht funktioniert (FileSystemNotFoundException: Provider "vfs" not installed
siehe auch diesen Beitrag ). Darüber hinaus ist es wie der ursprüngliche Code nicht threadsicher, wie von errr vorgeschlagen . Aus diesen Gründen habe ich diese Lösung aufgegeben; Wenn Sie diese Probleme jedoch akzeptieren können, finden Sie hier meinen vorgefertigten Code:quelle
Hier ist eine Methode, die ich für "Alle JUnits unter einem Paket ausführen" geschrieben habe. Sie sollten in der Lage sein, es an Ihre Bedürfnisse anzupassen.
Edit: Ah, in diesem Fall möchten Sie vielleicht auch dieses Snippet (gleicher Anwendungsfall :))
quelle
Hier ist ein Beispiel für die Verwendung der Reflections- Bibliothek zum rekursiven Scannen des Klassenpfads anhand eines Regex-Namensmusters, das mit einigen Guava- Vorteilen erweitert wurde, um Ressourceninhalte abzurufen:
Dies funktioniert sowohl mit Gläsern als auch mit explodierten Klassen.
quelle
Eine JAR-Datei ist nur eine Zip-Datei mit einem strukturierten Manifest. Sie können die JAR-Datei mit den üblichen Java-Zip-Tools öffnen und den Dateiinhalt auf diese Weise scannen, Streams aufblasen usw. Verwenden Sie dies dann in einem getResourceAsStream-Aufruf, und es sollte alles gut gelaunt sein.
EDIT / nach Klarstellung
Ich habe eine Minute gebraucht, um mich an all die Kleinigkeiten zu erinnern, und ich bin mir sicher, dass es sauberere Möglichkeiten gibt, aber ich wollte sehen, dass ich nicht verrückt bin. In meinem Projekt ist image.jpg eine Datei in einem Teil der Haupt-JAR-Datei. Ich erhalte den Klassenlader der Hauptklasse (SomeClass ist der Einstiegspunkt) und verwende ihn, um die Ressource image.jpg zu ermitteln. Dann etwas Stream-Magie, um es in dieses ImageInputStream-Ding zu bekommen, und alles ist in Ordnung.
quelle
new File("blah.JAR")
damit beispielsweise ein Dateiobjekt erstellen, das die JAR darstellt. Ersetzen Sie einfach "blah.JAR" durch den Namen Ihres JAR.Bei einer tatsächlichen JAR-Datei können Sie den Inhalt mit auflisten
JarFile.entries()
. Sie müssen jedoch den Speicherort der JAR-Datei kennen - Sie können den Klassenladeprogramm nicht einfach bitten, alles aufzulisten, worauf es ankommen könnte.Sie sollten in der Lage sein, den Speicherort der JAR-Datei anhand der von zurückgegebenen URL zu ermitteln
ThisClassName.class.getResource("ThisClassName.class")
, aber es kann ein wenig umständlich sein.quelle
new File("baz.jar)
das File-Objekt Ihre JAR-Datei darstellen würde , wenn Sie Code in Ihrem Jar hätten.Vor einiger Zeit habe ich eine Funktion erstellt, die innerhalb von JAR klasse wird:
quelle
quelle
Es gibt zwei sehr nützliche Dienstprogramme namens JarScan:
www.inetfeedback.com/jarscan
jarscan.dev.java.net
Siehe auch diese Frage: JarScan, scannt alle JAR-Dateien in allen Unterordnern nach einer bestimmten Klasse
quelle
Der robusteste Mechanismus zum Auflisten aller Ressourcen im Klassenpfad ist derzeit die Verwendung dieses Musters mit ClassGraph , da es die größtmögliche Anzahl von Klassenpfadspezifikationsmechanismen verarbeitet , einschließlich des neuen JPMS-Modulsystems. (Ich bin der Autor von ClassGraph.)
Es gibt auch viele andere Möglichkeiten, mit Ressourcen umzugehen .
quelle
Nur eine andere Art, Dateien von einer JAR-URL aufzulisten / zu lesen, und dies rekursiv für verschachtelte Jars
https://gist.github.com/trung/2cd90faab7f75b3bcbaa
quelle
Noch eine für die Straße:
Dies ist etwas flexibler für das Abgleichen bestimmter Dateinamen, da Wildcard-Globbing verwendet wird.
Ein funktionalerer Stil:
quelle