Comment obtenir un chemin d'accès à une ressource dans un fichier jar Java

J'essaie d'obtenir un chemin vers une ressource mais je n'ai pas eu de chance.

Cela fonctionne (à la fois dans IDE et avec le JAR) mais de cette façon je ne peux pas obtenir un chemin vers un fichier, seulement le contenu du fichier:

ClassLoader classLoader = getClass().getClassLoader();
PrintInputStream(classLoader.getResourceAsStream("config/netclient.p"));

Si je fais ceci:

ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource("config/netclient.p").getFile());

Le résultat est: java.io.FileNotFoundException: file:/path/to/jarfile/bot.jar!/config/netclient.p (No such file or directory)

Existe-t-il un moyen d'obtenir un chemin vers un fichier de ressources?

135
demandé sur no_ripcord 2009-06-03 00:32:46

14 réponses

C'est délibéré. Le contenu du "fichier" peut ne pas être disponible en tant que Fichier. Rappelez-vous que vous avez affaire à des classes et des ressources qui peuvent faire partie d'un fichier JAR ou d'un autre type de ressource. Le classloader n'a pas besoin de fournir un handle de fichier à la ressource, par exemple le fichier jar peut ne pas avoir été étendu dans des fichiers individuels dans le système de fichiers.

Tout ce que vous pouvez faire en obtenant un fichier java. io. peut être fait en copiant le flux dans un fichier temporaire et en faisant le idem, si un fichier java. io. est absolument nécessaire.

67
répondu Neal Maloney 2009-06-02 20:39:35

Lors du chargement d'une ressource, assurez-vous de remarquer la différence entre:

getClass().getClassLoader().getResource("com/myorg/foo.jpg") //relative path

Et

getClass().getResource("/com/myorg/foo.jpg")); //note the slash at the beginning

Je suppose que cette confusion cause la plupart des problèmes lors du chargement d'une ressource.


Aussi, lorsque vous chargez une image, il est plus facile d'utiliser getResourceAsStream():

BufferedImage image = ImageIO.read(getClass().getResourceAsStream("/com/myorg/foo.jpg"));

Lorsque vous devez vraiment charger un fichier (non-image) à partir d'une archive JAR, vous pouvez essayer ceci:

    File file = null;
    String resource = "/com/myorg/foo.xml";
    URL res = getClass().getResource(resource);
    if (res.toString().startsWith("jar:")) {
        try {
            InputStream input = getClass().getResourceAsStream(resource);
            file = File.createTempFile("tempfile", ".tmp");
            OutputStream out = new FileOutputStream(file);
            int read;
            byte[] bytes = new byte[1024];

            while ((read = input.read(bytes)) != -1) {
                out.write(bytes, 0, read);
            }
            file.deleteOnExit();
        } catch (IOException ex) {
            Exceptions.printStackTrace(ex);
        }
    } else {
        //this will probably work in your IDE, but not from a JAR
        file = new File(res.getFile());
    }

    if (file != null && !file.exists()) {
        throw new RuntimeException("Error: File " + file + " not found!");
    }
42
répondu Tombart 2018-04-10 05:01:53

La réponse d'une ligne est -

String path = this.getClass().getClassLoader().getResource(<resourceFileName>).toExternalForm()

Fondamentalement getResource méthode donne l'URL. À partir de cette URL, vous pouvez extraire le chemin en appelant toExternalForm()

Références:

GetResource(), toExternalForm()

19
répondu Manojkumar Khotele 2017-08-30 20:49:17

J'ai passé un moment à jouer avec ce problème, car aucune solution que j'ai trouvée n'a fonctionné, curieusement! Le répertoire de travail n'est souvent pas le répertoire du JAR, surtout si un JAR (ou n'importe quel programme, d'ailleurs) est exécuté à partir du Menu Démarrer sous Windows. Voici donc ce que j'ai fait, et ça marche .les fichiers de classe s'exécutent à l'extérieur d'un JAR aussi bien que cela fonctionne pour un JAR. (Je l'ai seulement testé sous Windows 7.)

try {
    //Attempt to get the path of the actual JAR file, because the working directory is frequently not where the file is.
    //Example: file:/D:/all/Java/TitanWaterworks/TitanWaterworks-en.jar!/TitanWaterworks.class
    //Another example: /D:/all/Java/TitanWaterworks/TitanWaterworks.class
    PROGRAM_DIRECTORY = getClass().getClassLoader().getResource("TitanWaterworks.class").getPath(); // Gets the path of the class or jar.

    //Find the last ! and cut it off at that location. If this isn't being run from a jar, there is no !, so it'll cause an exception, which is fine.
    try {
        PROGRAM_DIRECTORY = PROGRAM_DIRECTORY.substring(0, PROGRAM_DIRECTORY.lastIndexOf('!'));
    } catch (Exception e) { }

    //Find the last / and cut it off at that location.
    PROGRAM_DIRECTORY = PROGRAM_DIRECTORY.substring(0, PROGRAM_DIRECTORY.lastIndexOf('/') + 1);
    //If it starts with /, cut it off.
    if (PROGRAM_DIRECTORY.startsWith("/")) PROGRAM_DIRECTORY = PROGRAM_DIRECTORY.substring(1, PROGRAM_DIRECTORY.length());
    //If it starts with file:/, cut that off, too.
    if (PROGRAM_DIRECTORY.startsWith("file:/")) PROGRAM_DIRECTORY = PROGRAM_DIRECTORY.substring(6, PROGRAM_DIRECTORY.length());
} catch (Exception e) {
    PROGRAM_DIRECTORY = ""; //Current working directory instead.
}
12
répondu DeProgrammer 2011-03-17 22:24:20

Si netclient.p se trouve dans un fichier JAR, il n'aura pas de chemin car ce fichier se trouve dans un autre fichier. dans ce cas, le meilleur chemin que vous pouvez avoir est vraiment file:/path/to/jarfile/bot.jar!/config/netclient.p.

8
répondu cd1 2009-06-02 20:43:43

, Vous devez comprendre le chemin dans le fichier jar.
Il suffit de se référer à ce relatif. Donc, si vous avez un fichier (myfile.txt), situé à foo.jar sous le répertoire \src\main\resources (style maven). Vous y référeriez comme:

src/main/resources/myfile.txt

Si vous videz votre jar en utilisant jar -tvf myjar.jar vous verrez la sortie et le chemin relatif dans le fichier jar, et utilisez les barres obliques.

6
répondu eric manley 2016-02-18 13:18:43

Un fichier est une abstraction pour un fichier dans un système de fichiers, et les systèmes de fichiers ne savent rien sur le contenu d'un fichier JAR.

Essayez avec un URI, je pense qu'il y a un protocole jar:// qui pourrait être utile pour vos purpouses.

2
répondu fortran 2009-06-02 20:44:28

C'est le même code de L'utilisateur Tombart avec flux flush et close pour éviter une copie incomplète du contenu du fichier temporaire de la ressource jar et pour avoir des noms de fichiers temporaires uniques.

     File file = null;
        String resource = "/view/Trial_main.html" ;
        URL res = getClass().getResource(resource);
        if (res.toString().startsWith("jar:")) {
            try {
                InputStream input = getClass().getResourceAsStream(resource);
                file = File.createTempFile(new Date().getTime()+"", ".html");
                OutputStream out = new FileOutputStream(file);
                int read;
                byte[] bytes = new byte[1024];

                while ((read = input.read(bytes)) != -1) {
                    out.write(bytes, 0, read);
                }
                out.flush();
                out.close();
                input.close();
                file.deleteOnExit();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        } else {
            //this will probably work in your IDE, but not from a JAR
            file = new File(res.getFile());
        }
2
répondu Bruce 2015-02-25 18:31:22

Dans mon cas, j'ai utilisé un objet URL à la place du chemin.

Fichier

File file = new File("my_path");
URL url = file.toURI().toURL();

Ressource dans classpath en utilisant classloader

URL url = MyClass.class.getClassLoader().getResource("resource_name")

Quand j'ai besoin de lire le contenu, je peux utiliser le code suivant:

InputStream stream = url.openStream();

Et vous pouvez accéder au contenu en utilisant un InputStream.

2
répondu jmgoyesc 2017-03-02 14:07:43

Ce n'est pas la manière optimale de charger les ressources, mais si vous devez absolument avoir une référence java.io.File, Essayez de suivre:

 URL url = null;
  try {
     URL baseUrl = YourClass.class.getResource(".");
     if (baseUrl != null) {
        url = new URL(baseUrl, "yourfilename.ext");
     } else {
        url = YourClass.class.getResource("yourfilename.ext");
     }
  } catch (MalformedURLException e) {
     // Do something appropriate
  }

Cela vous donne un java.net.URL et il peut être utilisé dans un java.io.File constructeur.

1
répondu Jes 2012-05-22 13:13:34

Le chemin suivant a fonctionné pour moi: classpath:/path/to/resource/in/jar

1
répondu Anatoly 2012-10-10 18:10:24
private static final String FILE_LOCATION = "com/input/file/somefile.txt";

//Method Body


InputStream invalidCharacterInputStream = URLClassLoader.getSystemResourceAsStream(FILE_LOCATION);

Obtenir ce à partir de getSystemResourceAsStream est la meilleure option. En obtenant le inputstream plutôt que le fichier ou L'URL, fonctionne dans un fichier JAR et comme autonome.

1
répondu Shano 2014-04-14 05:01:45

Dans un fichier jar, la ressource se trouve absolument dans la hiérarchie des paquets (pas dans la hiérarchie du système de fichiers). Donc, si vous avez la classe com.exemple.Sweet chargement d'une ressource nommée "./défaut.conf "alors le nom de la ressource est spécifié comme" / com / example / default.conf".

Mais si c'est dans un pot, ce N'est pas un fichier ...

0
répondu Vilnis Krumins 2014-02-16 16:55:42

Dans votre dossier ressources (java/main/resources) de votre jar ajoutez votre fichier (nous supposons que vous avez ajouté un fichier xml nommé importations.xml), après que vous injectez ResourceLoader si vous utilisez le printemps comme ci-dessous

@Autowired
private ResourceLoader resourceLoader;

À l'intérieur tour fonction écrire le ci-dessous code afin de charger le fichier:

    Resource resource = resourceLoader.getResource("classpath:imports.xml");
    try{
        File file;
        file = resource.getFile();//will load the file
...
    }catch(IOException e){e.printStackTrace();}
0
répondu BERGUIGA Mohamed Amine 2017-10-20 09:00:20