[Solved][Java]Chemin relatif & FileReader

Bonjour,
J’explique mon problème : j’ai un programme Java qui utilise plusieurs templates.
Ces templates sont des fichiers qui se trouve, à l’heure actuelle, dans un package “templates” de mon appli sous Netbeans.
Donc, en gros, j’ai une arborescence qui ressemble à ca :

monProjetNetBeans
|__src
| |main
| |

| |__templates
|dist
|

L’application se trouve donc dans le dossier main, et mes templates, ben… dans le dossier templates.
Pour le moment (depuis Netbeans donc) je passe par le code suivant pour accéder à mes templates :

où templatePath vaut “\src\template” et templateName correspond au template que je veux utiliser parmi ceux qui sont dispo.

Le problème que je me pose, c’est comment faire pour accéder à ces templates en utilisant -par exemple- le jar une fois l’appli déployée, en sachant qu’ils sont inclus dans le jar généré par Netbeans. De plus, l’appli doit pouvoir tourner sous à peu près toute les plateform (MacOS, Linux et Windows).

J’ai déjà pas mal de librairie qui devront être placées dans le CLASSPATH, mais je préfèrerais pas que l’utilisateur touche aux templates. Donc, s’ils pouvaient rester dans le jar ça m’arrangerai pas mal.

Alors, je vous le demande… Comment faire?
Merci.

A vérifier mais il me semble bien que si tu fais new FileReader("/myPackage/myFile"); il ira lire le fichier directement dans le jar, dans le package qui va bien (ne pas oublier le “/” initial qui désigne la racine de l’arborescence de ton jar).


marche pas. J'ai regardé la structure du jar, les templates se trouvent directement dans le dossier "templates" du jar mais ça passe pas.

marche pas. J’ai regardé la structure du jar, les templates se trouvent directement dans le dossier “templates” du jar mais ça passe pas.

Ok my bad. (le .Net a commencer à me bouffer le cerveau et à me faire oublier mes bases, misère :slight_smile: )
En fait cette histoire de racine du jar ça marche avec Class.getRessource("/mypackage/myFile");
Cf la javadoc qui va bien.

Voici un exemple pour une icône.
Tu peux récupérer un objet URL (que tu passes au constructeur de File) ou bien directement un InputStream.

Normalement là ça devrait faire ce que tu cherches.

Ca m’a l’air tout bon, maintenant faut juste que je trouve comment faire mon getClass() depuis une méthode static ^^.

Le getClass se fait depuis un objet pour pouvoir utiliser le ClassLoader de l’objet en question et donc accéder au jar qui a permis de charger l’objet.
Donc dans ta méthode statique rien ne t’empêche de faire: “new Object().getClass()”.

kof kof… Oui tu as raison… (j’ai un peu honte)
Soit, en utilisant donc le getRessource() sur lequel je récupère l’URI du fichier pour ouvrir mon fichier, ca marche depuis netbeans mais dès que j’essais en exécutant le jar ca plante avec un message d’erreur :

URI is not hierarchical
java.lang.IllegalArgumentException: URI is not hierarchical
at java.io.File.(File.java:363)
at main.RATranslator.setTemplate(RATranslator.java:68)

avec le code suivant à la ligne correspondante :

FileReader templateFile = new FileReader((new File(new RATranslator().getClass() .getClassLoader().getResource("templates/" + templateName).toURI())));

Une idée?
Allez Twin ce soir on termine mon travail de diplôme au lieu d’aller boire des bières et je te rajoute dans les remerciements de mon mémoire :slight_smile:

EDIT :

En faisant moins le boulet, ca donne ca :

FileReader templateFile = new FileReader(new RATranslator().getClass() .getClassLoader().getResource("templates/" + templateName).getFile());

Et toujours pareil, enfin presque : ca fonctionne depuis Netbeans, mais depuis le jar :
Java.io.FileNotFoundException: file:\D:\Diplome\RATranslatorDev\dist\RATranslatorDev.jar!\templates\postgresqlTemplate (Syntaxe du nom de fichier, de rÚpertoire
ou de volume incorrecte)

D’après Google et le premier lien qu’il donne pour ton exception (« java.lang.IllegalArgumentException: URI is not hierarchical »), tu ne peux tout simplement pas utiliser l’API File pour lire des fichiers internes aux jars. :crying:
J’ignore si c’est vraiment le cas, mais je pense que ça vaut le coup d’essayer de se débrouiller en passant par des streams:

InputStream stream = new RATranslator().getClass() .getClassLoader().getResourceAsStream("templates/" + templateName)); BufferedReader reader = new BufferedReader(new InputStreamReader(stream ));

Code non testé, à toi de me dire si ça marche. :slight_smile:
Note l’utilisation de getResourceAsStream() à la place de getResource(), ainsi que l’utilisation du stream directement, pas de son URI.
Tu récupère un BufferedReader au lieu du FileReader mais je pense que ça reste utilisable pour ce que tu veux en tirer.

Merci beaucoup, je teste ca demain et je te tiens au courant.

EDIT : Ca marche !!!
Merci, merci, merci ! :slight_smile:

J’arrive après la bataille mais la solution de Twin est bien la meilleur à savoir :

[quote=“Twin, post:8, topic: 46709”]InputStream stream = new RATranslator().getClass() .getClassLoader().getResourceAsStream("templates/" + templateName)); BufferedReader reader = new BufferedReader(new InputStreamReader(stream ));[/quote]

[quote=“Twin, post:8, topic: 46709”]InputStream stream = new RATranslator().getClass() .getClassLoader().getResourceAsStream("templates/" + templateName)); BufferedReader reader = new BufferedReader(new InputStreamReader(stream ));[/quote]

Il me semble qu’il vaut mieux éviter d’instancier des objets quand ce n’est pas nécessaire. Ce n’est pas mieux comme ceci ?

InputStream stream = RATranslator.class.getClassLoader().getResourceAsStream("templates/" + templateName)); BufferedReader reader = new BufferedReader(new InputStreamReader(stream ));

Il me semble que ton code ne fonctionne que si la classe RATranslator est une classe static. Ce qui tombe bien, puisque c’est ce que je cherchais à faire.
Sauf que finalement, l’appel ne se fait plus depuis une méthode static. :slight_smile:

Maintenant que le programme tourne au poil, je fais faire mon diagramme UML :crying:

Tout à fait, tu peux utiliser this.getClass().getClassLoader() si tu préfères.

[quote=« DexterWard, post:12, topic: 46709 »]Il me semble que ton code ne fonctionne que si la classe RATranslator est une classe static. Ce qui tombe bien, puisque c’est ce que je cherchais à faire.
Sauf que finalement, l’appel ne se fait plus depuis une méthode static. :cry:

Maintenant que le programme tourne au poil, je fais faire mon diagramme UML :P[/quote]
Une classe static ? :crying: Il doit y avoir un problème dans la formulation car je comprends pas ce que tu veux dire.
Cela dit, il me semble que ma méthode marche dans une méthode static ou non. Ce n’est pas parce que je fais appel à l’attribut static « class » que je dois être dans une méthode static.

Tout à fait, sauf que c’est pas ce que j’ai dit. :slight_smile:

Aux temps pour moi, j’ai mal lu ton code.
Et oui, autant ce faire que peu de créer un nouvel objet. Oui ca veut rien dire, et alors!? Je craque ca fait 3 semaine que je bosse non stop.

En tous cas, merci beaucoup pour votre aide, même toi ZGoblin qui dit que des conneries en retard :slight_smile:

Oui il faut éviter les instanciations inutiles, quand on est au milieu d’une grosse boucle ou pour des objets élémentaires présents en grand nombre.

Pour le lecture d’un template qui ne se produira probablement pas toutes les millisecondes… il faut avoir une certaine affinité pour les galipettes déviantes avec les mouches pour avoir envie d’optimiser à ce point là. :slight_smile:

[quote=« Twin, post:16, topic: 46709 »]Oui il faut éviter les instanciations inutiles, quand on est au milieu d’une grosse boucle ou pour des objets élémentaires présents en grand nombre.

Pour le lecture d’un template qui ne se produira probablement pas toutes les millisecondes… il faut avoir une certaine affinité pour les galipettes déviantes avec les mouches pour avoir envie d’optimiser à ce point là. :crying:[/quote]

Gna gna gna. Ma vie privée avec les hyménoptères ne te regarde pas :slight_smile:
C’est toujours bien de prendre des bonnes habitudes, ça évitera de faire l’erreur plus tard « quand on est au milieu d’une grosse boucle ou pour des objets élémentaires présents en grand nombre ».
Cela dit, c’est pas non plus comme si je préconisais de faire ++i à la place de i++ (je laisse ça pour des gens comme c0unt0) :cry:

Je sais, j’ai proposé ça comme une solution supplémentaire à ta MaClasse.class.getClassLoader().

J’ai dis quoi comme conneries ? :crying: