Gibt es eine API, um eine Klassenpfadressource (z. B. was ich erhalten würde Class.getResource(String)
) als zu erhalten java.nio.file.Path
? Idealerweise möchte ich die ausgefallenen neuen Path
APIs mit Klassenpfadressourcen verwenden.
143
Paths.get(URI)
wenn Sie den langen Weg nehmen (Wortspiel beabsichtigt), haben Sie dann ´URL.toURI (), and last
getResource () `, das a zurückgibtURL
. Möglicherweise können Sie diese miteinander verketten. Habe es aber nicht versucht.Antworten:
Dieser funktioniert für mich:
quelle
Thread.currentThread().getContextClassLoader().getResource(resourceName).toURI()
Vermutlich möchten Sie Files.lines (...) für eine Ressource aufrufen, die aus dem Klassenpfad stammt - möglicherweise aus einem Glas.
Da Oracle die Vorstellung, dass ein Pfad ein Pfad ist, verschlungen hat, indem getResource keinen verwendbaren Pfad zurückgibt, wenn er sich in einer JAR-Datei befindet, müssen Sie Folgendes tun:
quelle
class.getResource
erfordert aber in meinem Fall einen Schrägstrich,getSystemResourceAsStream
kann die Datei jedoch nicht finden, wenn ein Schrägstrich vorangestellt ist.Die allgemeinste Lösung lautet wie folgt:
Das Haupthindernis besteht darin, sich mit den beiden Möglichkeiten zu befassen, entweder ein vorhandenes Dateisystem zu haben, das wir verwenden, aber nicht schließen sollten (wie bei
file
URIs oder dem Modulspeicher von Java 9), oder das Dateisystem selbst zu öffnen und somit sicher zu schließen (wie zip / jar-Dateien).Daher kapselt die obige Lösung die eigentliche Aktion in a
interface
, behandelt beide Fälle, schließt sie anschließend im zweiten Fall sicher und arbeitet von Java 7 bis Java 10. Sie prüft, ob bereits ein offenes Dateisystem vorhanden ist, bevor ein neues geöffnet wird funktioniert auch für den Fall, dass eine andere Komponente Ihrer Anwendung bereits ein Dateisystem für dieselbe Zip / JAR-Datei geöffnet hat.Es kann in allen oben genannten Java-Versionen verwendet werden, z. B. um den Inhalt eines Pakets (
java.lang
im Beispiel) wiePath
folgt aufzulisten :Mit Java 8 oder neuer können Sie Lambda-Ausdrücke oder Methodenreferenzen verwenden, um die tatsächliche Aktion darzustellen, z
das Gleiche tun.
Die endgültige Version des Java 9-Modulsystems hat das obige Codebeispiel beschädigt. Die JRE gibt den Pfad
/java.base/java/lang/Object.class
für inkonsistent zurück,Object.class.getResource("Object.class")
während dies der Fall sein sollte/modules/java.base/java/lang/Object.class
. Dies kann behoben werden, indem das Fehlende vorangestellt wird,/modules/
wenn der übergeordnete Pfad als nicht vorhanden gemeldet wird:Dann funktioniert es wieder mit allen Versionen und Speichermethoden.
quelle
Es stellt sich heraus, dass Sie dies mit Hilfe des eingebauten Systems tun können Anbieters Zip-Dateisysteme . Das direkte Übergeben eines Ressourcen-URI an
Paths.get
jedoch funktioniert nicht. Stattdessen muss zuerst ein Zip-Dateisystem für den JAR-URI ohne den Eintragsnamen erstellt und dann auf den Eintrag in diesem Dateisystem verwiesen werden:Aktualisieren:
Es wurde zu Recht darauf hingewiesen, dass der obige Code ein Ressourcenleck enthält, da der Code ein neues FileSystem-Objekt öffnet, es jedoch niemals schließt. Der beste Ansatz besteht darin, ein verbraucherähnliches Arbeiterobjekt zu übergeben, ähnlich wie es Holgers Antwort tut. Öffnen Sie das ZipFS-Dateisystem gerade lange genug, damit der Worker alles tun kann, was er mit dem Pfad tun muss (solange der Worker nicht versucht, das Path-Objekt für die spätere Verwendung zu speichern), und schließen Sie dann das Dateisystem.
quelle
newFileSystem
dazu führen, dass mehrere Ressourcen für immer offen bleiben. Obwohl @raisercostin Nachtrag vermeidet den Fehler , wenn ein bereits angelegtes Dateisystem zu erstellen versuchen, wenn Sie versuchen , das zu verwenden , zurückPath
Sie erhaltenClosedFileSystemException
. @ Holger Antwort funktioniert gut für mich.FileSystem
. Wenn Sie eine Ressource aus einem Glas laden, und Sie erstellen Sie dann die erforderlicheFileSystem
- dasFileSystem
erlaubt es Ihnen auch andere Ressourcen aus dem gleichen Glas zu laden. Sobald Sie die neue erstellt habenFileSystem
, können Sie einfach versuchen, die Ressource erneut mit zu laden,Paths.get(Path)
und die Implementierung verwendet die neue automatischFileSystem
.#getPath(String)
Methode nicht für dasFileSystem
Objekt verwenden.Ich habe eine kleine Hilfsmethode geschrieben, um
Paths
aus Ihren Klassenressourcen zu lesen . Die Verwendung ist sehr praktisch, da nur eine Referenz der Klasse benötigt wird, in der Sie Ihre Ressourcen gespeichert haben, sowie der Name der Ressource selbst.quelle
Sie können keine URI aus Ressourcen in der JAR-Datei erstellen. Sie können es einfach in die temporäre Datei schreiben und dann verwenden (java8):
quelle
Lesen Sie eine Datei aus dem Ressourcenordner mit NIO in Java8
quelle
Sie müssen das Dateisystem definieren, um Ressourcen aus der JAR-Datei zu lesen, wie unter https://docs.oracle.com/javase/8/docs/technotes/guides/io/fsp/zipfilesystemprovider.html beschrieben . Es gelingt mir, die Ressource aus der JAR-Datei mit den folgenden Codes zu lesen:
quelle