Je charge un fichier texte depuis un package dans un fichier JAR compilé de mon projet Java. La structure de répertoire pertinente est la suivante:
/src/initialization/Lifepaths.txt
Le code utilisé pour charger le fichier est:
public class Lifepaths {
public static void execute() {
System.out.println(Lifepaths.class.getClass().
getResourceAsStream("/initialization/Lifepaths.txt"));
}
private Lifepaths() {}
//This is temporary; will eventually be called from outside
public static void main(String[] args) {execute();}
}
L'impression imprimera toujours null
, peu importe ce que j'utilise. Je ne sais pas pourquoi cela ne marche pas, alors j'ai aussi essayé:
"/src/initialization/Lifepaths.txt"
"initialization/Lifepaths.txt"
"Lifepaths.txt"
Ni l'un ni l'autre ne fonctionne. J'ailude nombreusesquestions jusqu'à présent sur le sujet, mais aucune d'entre elles n'a été utile - en général, elles recommandent simplement de charger les fichiers à l'aide du chemin racine, qui Je fais déjà. Cela, ou chargez simplement le fichier à partir du répertoire en cours (chargez simplement filename
), que j'ai également essayé. Le fichier est compilé dans le fichier JAR à l'emplacement approprié avec le nom approprié.
Comment résoudre ce problème?
Lifepaths.class.getClass().getResourceAsStream(...)
charge les ressources à l'aide du chargeur de classes du système. Il échoue évidemment car il ne voit pas vos fichiers JAR.
Lifepaths.class.getResourceAsStream(...)
charge les ressources à l'aide du même chargeur de classe que celui qui a chargé Lifepaths et il devrait avoir accès aux ressources de vos fichiers JAR.
Les règles sont les suivantes:
Et essaye:
Lifepaths.class.getResourceAsStream("/initialization/Lifepaths.txt")
au lieu de
Lifepaths.class.getClass().getResourceAsStream("/initialization/Lifepaths.txt")
(Je ne sais pas si cela fait une différence, mais le premier utilisera le bon ClassLoader/JAR, alors que je ne suis pas sûr du dernier)
Il existe donc plusieurs façons d’obtenir une ressource à partir d’un fichier jar, chacune d’elles ayant une syntaxe légèrement différente, le chemin devant être spécifié différemment.
La meilleure explication que j'ai vue est cet article de JavaWorld . Je vais résumer ici, mais si vous voulez en savoir plus, vous devriez consulter l'article.
Les méthodes
1) ClassLoader.getResourceAsStream()
.
Format: "/" - noms séparés; pas de "/" (tous les noms sont absolus).
Exemple: this.getClass().getClassLoader().getResourceAsStream("some/pkg/resource.properties");
2) Class.getResourceAsStream()
Format: "/" - noms séparés; "/" en tête indique les noms absolus; tous les autres noms sont relatifs au paquet de la classe
Exemple: this.getClass().getResourceAsStream("/some/pkg/resource.properties");
N'utilisez pas de chemins absolus, comparez-les au répertoire "ressources" de votre projet. Code rapide et sale qui affiche le contenu de MyTest.txt à partir du répertoire 'resources'.
@Test
public void testDefaultResource() {
// can we see default resources
BufferedInputStream result = (BufferedInputStream)
Config.class.getClassLoader().getResourceAsStream("MyTest.txt");
byte [] b = new byte[256];
int val = 0;
String txt = null;
do {
try {
val = result.read(b);
if (val > 0) {
txt += new String(b, 0, val);
}
} catch (IOException e) {
e.printStackTrace();
}
} while (val > -1);
System.out.println(txt);
}
Vous voudrez peut-être essayer ceci pour obtenir le flux, c’est d’abord obtenir l’URL puis l’ouvrir en tant que flux.
URL url = getClass().getResource("/initialization/Lifepaths.txt");
InputStream strm = url.openStream();
Une fois, j'avais une question similaire: La lecture du fichier txt de jar échoue mais la lecture de l'image fonctionne
Il semble y avoir un problème avec le ClassLoader que vous utilisez. Utilisez contextClassLoader pour charger la classe. Ceci indépendamment du fait que ce soit dans une méthode statique/non statique
Thread.currentThread().getContextClassLoader().getResourceAsStream
......
Je ne sais pas si cela m'aide, mais dans mon cas, ma ressource se trouvait dans le dossier/src/et cette erreur me renvoyait . J'ai ensuite déplacé l'image dans le dossier bin et le problème a été résolu.
Assurez-vous que votre répertoire de ressources (par exemple "src") se trouve dans votre chemin de classe (assurez-vous qu'il s'agit d'un répertoire source dans votre chemin de construction dans Eclipse).
Assurez-vous que clazz est chargé à partir du chargeur de classes principal.
Ensuite, pour charger src/initialization/Lifepaths.txt, utilisez
clazz.getResourceAsStream("/initialization/Lifepaths.txt");
Pourquoi: clazz.getResourcesAsStream(foo)
cherche foo dans dans le chemin de classe de clazz , par rapport au répertoire dans lequel clazz habite . Le "/" initial le fait charger à partir de la racine de n’importe quel répertoire du classpath de clazz.
À moins que vous ne soyez dans un conteneur quelconque, comme Tomcat, ou que vous fassiez directement quelque chose avec les chargeurs de classe, vous pouvez simplement traiter votre chemin de classe Eclipse/en ligne de commande comme le seul chemin de classe classloader.
Je me suis retrouvé dans un problème similaire. Depuis que j'utilise maven, je devais mettre à jour mon pom.xml pour y inclure quelque chose comme:
...
</dependencies>
<build>
<resources>
<resource>
<directory>/src/main/resources</directory>
</resource>
<resource>
<directory>../src/main/resources</directory>
</resource>
</resources>
<pluginManagement>
...
Notez la balise de ressource ici pour spécifier où se trouve ce dossier. Si vous avez des projets imbriqués (comme je le fais), vous souhaiterez peut-être obtenir des ressources d'autres zones que du module dans lequel vous travaillez. Cela permet d'éviter de conserver le même fichier dans chaque référentiel si vous utilisez des données de configuration similaires.
Dans mon cas, rien ne fonctionnait à moins que je supprime les espaces des noms de fichiers ...
Ce qui a fonctionné pour moi a été d’ajouter le fichier sous Mon projet/Ressources Java/src, puis d’utiliser
this.getClass().getClassLoader().getResourceAsStream(myfile.txt);
Je n'ai pas eu besoin d'ajouter explicitement ce fichier au chemin (l'ajouter à/src le fait apparemment)
Le chargeur de classe JVM par défaut utilisera parent-classloader pour charger les ressources en premier: .
Le chargeur de classes de Lifepaths.class.getClass()
est bootstrap classloader
, donc getResourceAsStream
ne cherchera que $ Java_HOME, quel que soit l'utilisateur fourni par classpath
. De toute évidence, Lifepaths.txt n’est pas là.
Le chargeur de classe de Lifepaths.class
est system classpath classloader
, donc getResourceAsStream
recherchera le classpath
défini par l'utilisateur et Lifepaths.txt sera présent.
Lorsque vous utilisez Java.lang.Class#getResourceAsStream(String name)
, le nom qui ne commence pas par '/' sera ajouté avec le préfixe package name
. Si vous voulez éviter cela, veuillez utiliser Java.lang.ClassLoader#getResourceAsStream
. Par exemple:
ClassLoader loader = Thread.currentThread().getContextClassLoader();
String resourceName = "Lifepaths.txt";
InputStream resourceStream = loader.getResourceAsStream(resourceName);