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:

  1. Recherche de la Class ou du ClassLoader qui trouvera la ressource.
  2. Trouver la ressource.
  3. Obtenir le flux d'octets pour la ressource.
  4. Lecture et traitement du flux d'octets.
  5. 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'objet Class pour le type String .

  • Object.getClass() vous donnera l'objet Class pour le type de n'importe quel objet; Par exemple, "hello".getClass() est un autre moyen d'obtenir la Class du type String .

  • La Class.forName(String) chargera (si nécessaire) dynamiquement une classe et renverra son objet Class ; par exemple Class.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 et Class 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.
  • Si la ressource (ou les ressources) demandée (s) est introuvable, les methods return getResource et getResourceAsStream methods return null , and the methods return an empty getResources methods 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 de file: URL ou d'autres URL classiques, mais si la ressource réside dans un fichier JAR, il s'agira d'URL jar: identifiant le fichier JAR et une ressource spécifique.

  • Si votre code utilise une méthode getResourceAsStream (ou URL.toStream() ) pour obtenir un InputStream , 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.



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow