web-dev-qa-db-fra.com

Fichier JAR Java: utiliser les erreurs de ressources: l'URI n'est pas hiérarchique

J'ai déployé mon application dans un fichier jar. Quand j'ai besoin de copier des données d'un fichier de ressource en dehors du fichier jar, je fais ce code:

URL resourceUrl = getClass().getResource("/resource/data.sav");
File src = new File(resourceUrl.toURI()); //ERROR HERE
File dst = new File(CurrentPath()+"data.sav");  //CurrentPath: path of jar file don't include jar file name
FileInputStream in = new FileInputStream(src);
FileOutputStream out = new FileOutputStream(dst);
 // some excute code here

L'erreur que j'ai rencontrée est: URI is not hierarchical. cette erreur, je ne rencontre pas quand exécuté dans IDE.

Si je modifie le code ci-dessus pour obtenir de l'aide sur un autre post sur StackOverFlow:

InputStream in = Model.class.getClassLoader().getResourceAsStream("/resource/data.sav");
File dst = new File(CurrentPath() + "data.sav");
FileOutputStream out = new FileOutputStream(dst);
//....
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) { //NULL POINTER EXCEPTION
  //....
}
50
hqt

Tu ne peux pas faire ça

File src = new File(resourceUrl.toURI()); //ERROR HERE

ce n'est pas un fichier! Lorsque vous sortez de l'ide, vous n'avez aucune erreur, parce que vous n'exécutez pas de fichier jar. Dans IDE, les classes et les ressources sont extraites sur le système de fichiers.

Mais vous pouvez ouvrir une InputStream de cette façon:

    InputStream in = Model.class.getClassLoader().getResourceAsStream("/data.sav");

Supprimer "/resource". En général, les IDE se séparent des ressources et des classes du système de fichiers. Mais lorsque le pot est créé, ils sont tous mis ensemble. Ainsi, le niveau de dossier "/resource" est utilisé uniquement pour la séparation de classes et de ressources.

Lorsque vous obtenez une ressource du chargeur de classe, vous devez spécifier le chemin d'accès de la ressource à l'intérieur du fichier jar. Il s'agit de la hiérarchie réelle du package.

82
dash1e

Si, pour une raison quelconque, vous devez réellement créer un objet Java.io.File pour qu'il pointe vers une ressource située dans un fichier Jar, la réponse est la suivante: https://stackoverflow.com/a/27149287/155167

File f = new File(getClass().getResource("/MyResource").toExternalForm());
12
Mario

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 de permettre l'accès à l'objet à l'aide de 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/

7
Ilya Buziuk

J'ai eu des problèmes similaires avant, et j'ai utilisé le code:

new File(new URI(url.toString().replace(" ","%20")).getSchemeSpecificPart());

au lieu du code:

new File(new URI(url.toURI())

résoudre le problème

0
Yukai Tang

En plus des réponses générales, vous pouvez obtenir la bibliothèque "La bibliothèque Unitils d'URI n'est pas hiérarchique" pour tenter de charger un ensemble de données sur un fichier .jar. Cela peut arriver lorsque vous conservez des jeux de données dans un sous-module Maven, mais que les tests sont effectués dans un autre. 

Il y a même un bug UNI-197 filed.

0
jediz

Pendant que je suis tombé sur ce problème moi-même, j'aimerais ajouter une autre option (à l'explication par ailleurs parfaite de @ dash1e): 

Exportez le plugin en tant que dossier (pas un jar) en ajoutant: 

Eclipse-BundleShape: dir

à votre MANIFEST.MF

Au moins, lorsque vous exportez votre application RCP à l'aide du fichier Assistant d’exportation (basé sur un fichier *.product), il est respecté et génère un dossier. 

0
Jens