web-dev-qa-db-fra.com

Pourquoi mon URI n'est-il pas hiérarchique?

J'ai des fichiers dans le dossier de ressources. Par exemple, si j'ai besoin d'obtenir un fichier du dossier de ressources, j'aime bien cela:

File myFile= new File(MyClass.class.getResource(/myFile.jpg).toURI());             
System.out.println(MyClass.class.getResource(/myFile.jpg).getPath());

J'ai testé et tout fonctionne!

Le chemin est

/D:/Java/projects/.../classes/X/Y/Z/myFile.jpg

Mais, Si je crée un fichier jar en utilisant, Maven:

mvn package

... puis lancez mon application:

Java -jar MyJar.jar

J'ai l'erreur suivante:

Exception in thread "Thread-4" Java.lang.RuntimeException: ხელმოწერის განხორციელება შეუძლებელია
Caused by: Java.lang.IllegalArgumentException: URI is not hierarchical
        at Java.io.File.<init>(File.Java:363)

...et le chemin du fichier est:

file:/D:/Java/projects/.../target/MyJar.jar!/X/Y/Z/myFile.jpg

Cette exception se produit lorsque j'essaie d'obtenir un fichier à partir du dossier de ressources. À cette ligne. Pourquoi? Pourquoi ce problème dans le fichier JAR? Qu'est-ce que tu penses?

Existe-t-il un autre moyen d'obtenir le chemin du dossier de ressources?

46
grep

Vous devriez utiliser

getResourceAsStream(...);

lorsque la ressource est regroupée sous forme de fichier jar/war ou de tout autre package de fichier unique pour cette question.

Vous voyez, un fichier jar est un fichier unique (un peu comme un fichier Zip) contenant beaucoup de fichiers. De pov d'Os, c'est un fichier unique et si vous voulez accéder à un part of the file (votre fichier image), vous devez l’utiliser comme un flux.

Documentation

70
rocketboy

Voici une solution pour les développeurs Eclipse RCP/Plugin:

Bundle bundle = Platform.getBundle("resource_from_some_plugin");
URL fileURL = bundle.getEntry("files/test.txt");
File file = null;
try {
   URL resolvedFileURL = FileLocator.toFileURL(fileURL);

   // We need to use the 3-arg constructor of URI in order to properly escape file system chars
   URI resolvedURI = new URI(resolvedFileURL.getProtocol(), resolvedFileURL.getPath(), null);
   File file = new File(resolvedURI);
} catch (URISyntaxException e1) {
    e1.printStackTrace();
} catch (IOException e1) {
    e1.printStackTrace();
}

Il est très important d'utiliser FileLocator.toFileURL(fileURL) plutôt que resolve(fileURL), car lorsque le plug-in est compressé dans un fichier jar, Eclipse crée une version décompressée dans un emplacement temporaire afin que l'objet puisse être accessible via Fichier. Par exemple, je suppose que Lars Vogel a une erreur dans son article - http://blog.vogella.com/2010/07/06/reading-resources-from-plugin/

11
Ilya Buziuk

Je suis confronté au même problème lorsque je travaillais sur un projet dans mon entreprise. Tout d'abord, l'URI n'est pas hiérarchique. C'est parce que vous utilisez probablement "/" comme séparateur de fichier.

Vous devez vous rappeler que "/" est pour Windows et qu'il change d'un système d'exploitation à l'autre. Il peut être différent sous Linux. Par conséquent, utilisez File.seperator .

Donc en utilisant

this.getClass().getClassLoader().getResource("res"+File.separator+"secondFolder")

peut supprimer l'URI non hierarchique. Mais maintenant, vous pouvez faire face à une exception de pointeur nul. J'ai essayé de nombreuses manières différentes, puis j'ai utilisé JarEntries Class pour le résoudre.

File jarFile = new File(this.getClass().getProtectionDomain().getCodeSource().getLocation().toURI().getPath());
        String actualFile = jarFile.getParentFile().getAbsolutePath()+File.separator+"Name_Of_Jar_File.jar";
        System.out.println("jarFile is : "+jarFile.getAbsolutePath());
        System.out.println("actulaFilePath is : "+actualFile);
        final JarFile jar = new JarFile(actualFile);
        final Enumeration<JarEntry> entries = jar.entries(); //gives ALL entries in jar
        System.out.println("Reading entries in jar file ");
        while(entries.hasMoreElements()) {
            JarEntry jarEntry = entries.nextElement();
            final String name = jarEntry.getName();
            if (name.startsWith("Might Specify a folder name you are searching for")) { //filter according to the path
                System.out.println("file name is "+name);
                System.out.println("is directory : "+jarEntry.isDirectory());
                File scriptsFile  = new File(name);
                System.out.println("file names are : "+scriptsFile.getAbsolutePath());

            }
        }
        jar.close();

Vous devez spécifier explicitement le nom du pot ici. Donc, utilisez ce code, cela vous donnera le répertoire et le sous-répertoire dans le dossier dans jar.

2
Prateek Mishra