Existe-t-il une API pour obtenir une ressource classpath (par exemple ce que j'obtiendrais Class.getResource(String)
) en tant que java.nio.file.Path
? Idéalement, j'aimerais utiliser les nouvelles Path
API sophistiquées avec des ressources de chemin de classe.
143
Paths.get(URI)
, alors ´URL.toURI (), and last
getResource () `qui retourne unURL
. Vous pourrez peut-être les enchaîner. Je n'ai pas essayé cependant.Réponses:
Celui-ci fonctionne pour moi:
la source
Thread.currentThread().getContextClassLoader().getResource(resourceName).toURI()
Je suppose que ce que vous voulez faire, c'est d'appeler Files.lines (...) sur une ressource qui provient du classpath - peut-être depuis un fichier jar.
Étant donné qu'Oracle a compliqué la notion de quand un chemin est un chemin en ne faisant pas que getResource renvoie un chemin utilisable s'il réside dans un fichier jar, ce que vous devez faire est quelque chose comme ceci:
la source
class.getResource
nécessite une barre oblique maisgetSystemResourceAsStream
ne peut pas trouver le fichier lorsqu'il est préfixé par une barre oblique.La solution la plus générale est la suivante:
Le principal obstacle est de gérer les deux possibilités, soit d'avoir un système de fichiers existant que nous devrions utiliser, mais pas de fermer (comme avec les
file
URI ou le stockage de modules de Java 9), soit d'avoir à ouvrir et donc fermer en toute sécurité le système de fichiers nous-mêmes (comme zip / jar).Par conséquent, la solution ci-dessus encapsule l'action réelle dans un
interface
, gère les deux cas, se fermant ensuite en toute sécurité dans le second cas, et fonctionne de Java 7 à Java 10. Elle vérifie s'il existe déjà un système de fichiers ouvert avant d'en ouvrir un nouveau, donc il fonctionne également dans le cas où un autre composant de votre application a déjà ouvert un système de fichiers pour le même fichier zip / jar.Il peut être utilisé dans toutes les versions de Java nommées ci-dessus, par exemple pour lister le contenu d'un paquet (
java.lang
dans l'exemple) en tant quePath
s, comme ceci:Avec Java 8 ou plus récent, vous pouvez utiliser des expressions lambda ou des références de méthode pour représenter l'action réelle, par exemple
Faire la même chose.
La version finale du système de modules de Java 9 a cassé l'exemple de code ci-dessus. Le JRE renvoie de manière incohérente le chemin
/java.base/java/lang/Object.class
pourObject.class.getResource("Object.class")
alors qu'il devrait l'être/modules/java.base/java/lang/Object.class
. Cela peut être résolu en ajoutant les éléments manquants/modules/
lorsque le chemin parent est signalé comme inexistant:Ensuite, il fonctionnera à nouveau avec toutes les versions et méthodes de stockage.
la source
Il s'avère que vous pouvez le faire, avec l'aide du fournisseur de système de fichiers Zip intégré . Cependant, passer directement un URI de ressource à
Paths.get
ne fonctionnera pas; au lieu de cela, il faut d'abord créer un système de fichiers zip pour l'URI jar sans le nom d'entrée, puis se référer à l'entrée dans ce système de fichiers:Mettre à jour:
Il a été souligné à juste titre que le code ci-dessus contient une fuite de ressources, car le code ouvre un nouvel objet FileSystem mais ne le ferme jamais. La meilleure approche consiste à transmettre un objet worker de type Consumer, tout comme la réponse de Holger le fait. Ouvrez le système de fichiers ZipFS juste assez longtemps pour que le travailleur fasse tout ce qu'il doit faire avec le chemin (tant que le travailleur n'essaye pas de stocker l'objet Chemin pour une utilisation ultérieure), puis fermez le système de fichiers.
la source
newFileSystem
peut conduire à plusieurs ressources qui restent ouvertes pour toujours. Bien que l'addendum @raisercostin évite l'erreur lorsque vous essayez de créer un système de fichiers déjà créé, si vous essayez d'utiliser le fichier renvoyé,Path
vous obtiendrez un fichierClosedFileSystemException
. La réponse @Holger fonctionne bien pour moi.FileSystem
. Si vous chargez une ressource à partir d'un Jar et que vous créez ensuite le fichier requisFileSystem
,FileSystem
cela vous permettra également de charger d'autres ressources à partir du même Jar. De plus, une fois que vous avez créé le nouveau,FileSystem
vous pouvez simplement essayer de charger à nouveau la ressource en utilisantPaths.get(Path)
et l'implémentation utilisera automatiquement le nouveauFileSystem
.#getPath(String)
méthode sur l'FileSystem
objet.J'ai écrit une petite méthode d'aide à lire à
Paths
partir de vos ressources de classe. Il est assez pratique à utiliser car il ne nécessite qu'une référence de la classe dans laquelle vous avez stocké vos ressources ainsi que le nom de la ressource elle-même.la source
Vous ne pouvez pas créer d'URI à partir des ressources à l'intérieur du fichier jar. Vous pouvez simplement l'écrire dans le fichier temporaire, puis l'utiliser (java8):
la source
Lire un fichier à partir du dossier de ressources à l'aide de NIO, dans java8
la source
Vous devez définir le système de fichiers pour lire la ressource à partir du fichier jar comme indiqué dans https://docs.oracle.com/javase/8/docs/technotes/guides/io/fsp/zipfilesystemprovider.html . J'ai réussi à lire la ressource à partir du fichier jar avec les codes ci-dessous:
la source