Java Language
Ressources (sur classpath)
Recherche…
Introduction
Java permet la récupération des ressources basées sur des fichiers stockées dans un fichier JAR à côté des classes compilées. Cette rubrique se concentre sur le chargement de ces ressources et leur mise à disposition dans votre code.
Remarques
Une ressource est une donnée de type fichier avec un nom de chemin d'accès, qui réside dans le chemin de classe. L'utilisation la plus courante des ressources consiste à regrouper des images d'application, des sons et des données en lecture seule (telles que la configuration par défaut).
Les ressources sont accessibles avec les méthodes ClassLoader.getResource et ClassLoader.getResourceAsStream . Le cas d'utilisation le plus courant est d'avoir des ressources placées dans le même package que la classe qui les lit; les méthodes Class.getResource et Class.getResourceAsStream servent ce cas d'utilisation commun.
La seule différence entre une méthode getResource et la méthode getResourceAsStream est que la première renvoie une URL, tandis que la seconde ouvre cette URL et renvoie un InputStream.
Les méthodes de ClassLoader acceptent un nom de ressource de type chemin d'accès en tant qu'argument et effectuent une recherche dans chaque emplacement du chemin de classe du ClassLoader pour une entrée correspondant à ce nom.
- Si un emplacement de chemin de classe est un fichier .jar, une entrée jar avec le nom spécifié est considérée comme une correspondance.
- Si un emplacement de chemin de classe est un répertoire, un fichier relatif sous ce répertoire avec le nom spécifié est considéré comme une correspondance.
Le nom de la ressource est similaire à la portion de chemin d'une URL relative. Sur toutes les plateformes, il utilise des barres obliques ( /
) comme séparateurs de répertoires. Il ne doit pas commencer par une barre oblique.
Les méthodes correspondantes de la classe sont similaires, sauf:
- Le nom de la ressource peut commencer par une barre oblique, auquel cas cette barre oblique initiale est supprimée et le reste du nom est transmis à la méthode correspondante de ClassLoader.
- Si le nom de la ressource ne commence pas par une barre oblique, il est traité comme relatif à la classe dont la méthode getResource ou getResourceAsStream est appelée. Le nom de ressource réel devient package / name , où package est le nom du package auquel appartient la classe, chaque période étant remplacée par une barre oblique, et name est l'argument d'origine donné à la méthode.
Par exemple:
package com.example;
public class ExampleApplication {
public void readImage()
throws IOException {
URL imageURL = ExampleApplication.class.getResource("icon.png");
// The above statement is identical to:
// ClassLoader loader = ExampleApplication.class.getClassLoader();
// URL imageURL = loader.getResource("com/example/icon.png");
Image image = ImageIO.read(imageURL);
}
}
Les ressources doivent être placées dans des packages nommés, plutôt qu'à la racine d'un fichier .jar, pour la même raison, les classes sont placées dans des packages: pour empêcher les collisions entre plusieurs fournisseurs. Par exemple, si plusieurs chemins d'accès au fichier .jar se trouvent dans le chemin d'accès aux classes et que plusieurs d'entre eux contiennent une entrée config.properties
dans sa racine, les appels aux méthodes getResource ou getResourceAsStream renvoient config.properties. le classpath. Ce comportement n'est pas prévisible dans les environnements où l'ordre de classpath n'est pas sous le contrôle direct de l'application, tel que Java EE.
Toutes les méthodes getResource et getResourceAsStream renvoient null
si la ressource spécifiée n'existe pas. Comme les ressources doivent être ajoutées à l'application au moment de la construction, leurs emplacements doivent être connus lors de l'écriture du code; le fait de ne pas trouver une ressource à l'exécution est généralement le résultat d'une erreur du programmeur.
Les ressources sont en lecture seule. Il n'y a aucun moyen d'écrire sur une ressource. Les développeurs novices commettent souvent l'erreur de supposer que la ressource étant un fichier physique distinct lors du développement dans un IDE (comme Eclipse), il sera prudent de la traiter comme un fichier physique distinct dans le cas général. Cependant, ce n'est pas correct; les applications sont presque toujours distribuées sous forme d'archives telles que les fichiers .jar ou .war, et dans ce cas, une ressource ne sera pas un fichier distinct et ne sera pas accessible en écriture. (La méthode getFile de la classe d'URL n'est pas une solution de contournement pour cela; malgré son nom, elle renvoie simplement la portion de chemin d'une URL, ce qui n'est en aucun cas un nom de fichier valide.)
Il n'y a aucun moyen sûr de lister les ressources à l'exécution. Encore une fois, les développeurs étant responsables de l'ajout de fichiers de ressources à l'application au moment de la construction, les développeurs doivent déjà connaître leurs chemins. Bien qu'il existe des solutions de contournement, elles ne sont pas fiables et finiront par échouer.
Chargement d'une image à partir d'une ressource
Pour charger une image groupée:
package com.example;
public class ExampleApplication {
private Image getIcon() throws IOException {
URL imageURL = ExampleApplication.class.getResource("icon.png");
return ImageIO.read(imageURL);
}
}
Chargement de la configuration par défaut
Pour lire les propriétés de configuration par défaut:
package com.example;
public class ExampleApplication {
private Properties getDefaults() throws IOException {
Properties defaults = new Properties();
try (InputStream defaultsStream =
ExampleApplication.class.getResourceAsStream("config.properties")) {
defaults.load(defaultsStream);
}
return defaults;
}
}
Chargement d'une ressource de même nom à partir de plusieurs JAR
Une ressource ayant le même chemin et le même nom peut exister dans plusieurs fichiers JAR sur le chemin de classe. Les cas courants sont des ressources suivant une convention ou faisant partie d'une spécification d'emballage. Des exemples de telles ressources sont
- META-INF / MANIFEST.MF
- META-INF / beans.xml (Spéc. CDI)
- Propriétés ServiceLoader contenant des fournisseurs d'implémentation
Pour accéder à toutes ces ressources dans des fichiers JAR différents, il faut utiliser un ClassLoader, qui possède une méthode pour cela. L' Enumeration
renvoyée peut être facilement convertie en une List
utilisant une fonction Collections.
Enumeration<URL> resEnum = MyClass.class.getClassLoader().getResources("META-INF/MANIFEST.MF");
ArrayList<URL> resources = Collections.list(resEnum);
Recherche et lecture de ressources à l'aide d'un chargeur de classe
Le chargement de ressources en Java comprend les étapes suivantes:
- Recherche de la
Class
ou duClassLoader
qui trouvera la ressource. - Trouver la ressource.
- Obtenir le flux d'octets pour la ressource.
- Lecture et traitement du flux d'octets.
- Fermer le flux d'octets.
Les trois dernières étapes sont généralement accomplies en passant l'URL à une méthode de bibliothèque ou à un constructeur pour charger la ressource. Vous utiliserez généralement une méthode getResource
dans ce cas. Il est également possible de lire les données de la ressource dans le code de l'application. Vous utiliserez généralement getResourceAsStream
dans ce cas.
Chemins de ressource absolus et relatifs
Les ressources pouvant être chargées à partir du chemin de classe sont désignées par un chemin . La syntaxe du chemin est similaire à un chemin de fichier UNIX / Linux. Il se compose de noms simples séparés par des barres obliques ( /
). Un chemin relatif commence par un nom et un chemin absolu commence par un séparateur.
Comme le décrivent les exemples de Classpath, le chemin de classe d’une machine virtuelle Java définit un espace de noms en superposant les espaces de noms des répertoires et des fichiers JAR ou ZIP dans le chemin de classes. Lorsqu'un chemin absolu est résolu, les chargeurs de classes interprètent l'initial /
comme signifiant la racine de l'espace de noms. En revanche, un chemin relatif peut être résolu par rapport à n'importe quel "dossier" de l'espace de noms. Le dossier utilisé dépend de l'objet que vous utilisez pour résoudre le chemin.
Obtenir un cours ou un chargeur de classe
Une ressource peut être localisée à l'aide d'un objet Class
ou d'un objet ClassLoader
. Un objet Class
peut résoudre des chemins relatifs, vous utiliserez donc généralement l'un d'entre eux si vous avez une ressource relative (de classe). Il existe plusieurs façons d'obtenir un objet Class
. Par exemple:
Un littéral de classe vous donnera l'objet
Class
pour toute classe que vous pouvez nommer dans le code source Java; Par exemple,String.class
vous donne l'objetClass
pour le typeString
.Object.getClass()
vous donnera l'objetClass
pour le type de n'importe quel objet; Par exemple,"hello".getClass()
est un autre moyen d'obtenir laClass
du typeString
.La
Class.forName(String)
chargera (si nécessaire) dynamiquement une classe et renverra son objetClass
; par exempleClass.forName("java.lang.String")
.
Un objet ClassLoader
est généralement obtenu en appelant getClassLoader()
sur un objet Class
. Il est également possible de récupérer le classloader par défaut de la machine ClassLoader.getSystemClassLoader()
utilisant la méthode statique ClassLoader.getSystemClassLoader()
.
Les méthodes get
Une fois que vous avez une instance Class
ou ClassLoader
, vous pouvez rechercher une ressource en utilisant l'une des méthodes suivantes:
Les méthodes | La description |
---|---|
ClassLoader.getResource(path) ClassLoader.getResources(path) | Retourne une URL qui représente l'emplacement de la ressource avec le chemin donné. |
ClassLoader.getResources(path) Class.getResources(path) | Renvoie une Enumeration<URL> indiquant les URL pouvant être utilisées pour localiser la ressource foo.bar ; voir ci-dessous. |
ClassLoader.getResourceAsStream(path) Class.getResourceStream(path) | Renvoie un InputStream partir duquel vous pouvez lire le contenu de la ressource foo.bar sous la forme d'une séquence d'octets. |
Remarques:
La principale différence entre les versions
ClassLoader
etClass
des méthodes réside dans la manière dont les chemins relatifs sont interprétés.- Les méthodes
Class
résolvent un chemin d'accès relatif dans le "dossier" correspondant au package de classes. - Les méthodes
ClassLoader
traitent les chemins relatifs comme s'ils étaient absolus; c'est-à-dire les résoudre dans le "dossier racine" de l'espace de noms classpath.
- Les méthodes
Si la ressource (ou les ressources) demandée (s) est introuvable, les
methods return
getResource
et getResourceAsStreammethods return
null, and the
methods return an empty
getResourcesmethods return an empty
Enumeration`methods return an empty
.Les URL renvoyées pourront être
URL.toStream()
aide d'URL.toStream()
. Il peut s'agir d'URL defile:
URL ou d'autres URL classiques, mais si la ressource réside dans un fichier JAR, il s'agira d'URLjar:
identifiant le fichier JAR et une ressource spécifique.Si votre code utilise une méthode
getResourceAsStream
(ouURL.toStream()
) pour obtenir unInputStream
, il est responsable de la fermeture de l'objet de flux. Si vous ne fermez pas le flux, vous risquez de provoquer une fuite de ressources.