View Full Version : [Java] estrarre dal proprio JAR
immaginiamo di poter dare per scontato che un programma Java sia stato compresso in un file JAR assieme ad alcune risorse che dovrà utilizzare (facciamo delle immagini). i problemi che vedo sono principalmente due:
1) come ottenere il path del proprio file JAR
2) come estrarre dal JAR (questo è un problema solo mio, nel senso che so che si può fare a non so come ^^)
ed infine aggiungiamo anche un terzo problema:
3) esiste una maniera più semplice/diretta/affidabile? per esempio, in Win32 per caricare delle risorse dal proprio eseguibile non c'è mica bisogno di sapere il nome del file e di aprirlo a parte...
immaginiamo di poter dare per scontato che un programma Java sia stato compresso in un file JAR assieme ad alcune risorse che dovrà utilizzare (facciamo delle immagini). i problemi che vedo sono principalmente due:
1) come ottenere il path del proprio file JAR
2) come estrarre dal JAR (questo è un problema solo mio, nel senso che so che si può fare a non so come ^^)
ed infine aggiungiamo anche un terzo problema:
3) esiste una maniera più semplice/diretta/affidabile? per esempio, in Win32 per caricare delle risorse dal proprio eseguibile non c'è mica bisogno di sapere il nome del file e di aprirlo a parte...
Guardati i metodi getResource() e/o getResourceAsStream() di Class.
pare faccia al caso mio, però parla di risorse associate ad una classe; come si associa una risorsa ad una classe? una risorsa associata ad una classe può stare anche dentro un JAR?
lavoro con Eclipse e quando esporto i JAR mi permette di includervi anche cartelle non contenenti files binari .class. io ho messo tutte le mie immagini in una cartella "gfx", che nel filesystem si trova allo stesso livello delle cartelle "src" e "bin" in cui Eclipse mette di default i sorgenti e i binari (rispettivamente), quindi come procedo esattamente? va bene includere "gfx" nel JAR o devo includere separatamente le immagini in qualche altro modo? cosa passo poi di preciso a getResource(AsStream)?
altra domanda: vedo che getResource mi restituisce un URL... sarebbe l'URL di cosa? :confused: si, della risorsa, ok :D, ma sto URL a cosa punta? a una cartella temporanea nel filesystem locale dove la JVM ha estratto i files? o che altro?
^TiGeRShArK^
23-10-2007, 12:42
pare faccia al caso mio, però parla di risorse associate ad una classe; come si associa una risorsa ad una classe? una risorsa associata ad una classe può stare anche dentro un JAR?
lavoro con Eclipse e quando esporto i JAR mi permette di includervi anche cartelle non contenenti files binari .class. io ho messo tutte le mie immagini in una cartella "gfx", che nel filesystem si trova allo stesso livello delle cartelle "src" e "bin" in cui Eclipse mette di default i sorgenti e i binari (rispettivamente), quindi come procedo esattamente? va bene includere "gfx" nel JAR o devo includere separatamente le immagini in qualche altro modo? cosa passo poi di preciso a getResource(AsStream)?
altra domanda: vedo che getResource mi restituisce un URL... sarebbe l'URL di cosa? :confused: si, della risorsa, ok :D, ma sto URL a cosa punta? a una cartella temporanea nel filesystem locale dove la JVM ha estratto i files? o che altro?
Ogni risorsa messa all'interno di un file .jar può essere caricata utilizzando il classloader.
Il path non è altro che il percorso della risorsa espresso in termini di package.
Per esempio se hai un'immagine nella dir gfx/pamela.jpg basta che dici al classloader di darti la risorsa 'gfx/pamela.jpg' e provvede lui a fare tutto.
Stai attento alle varie modalità possibili per accedere ai package perchè puoi accedervi sia in maniera relativa che assoluta.
Una pagina web che spiega piuttosto bene tutto il meccanismo è questa:
http://www.javaworld.com/javaworld/javaqa/2003-08/01-qa-0808-property.html?page=2
Nonostante sia stata scrtta per il caricamento delle properties spiega bene le differenze tra i 3 metodi:
ClassLoader.getResourceAsStream ("some/pkg/resource.properties");
Class.getResourceAsStream ("/some/pkg/resource.properties");
ResourceBundle.getBundle ("some.pkg.resource");
Ovviamente però l'ultimo metodo funziona solo con file .properties mentre gli altri sono assolutamente generali :p
ok, funziona perfettamente :D
adesso ho un altro problema: non funziona più se eseguo le classi non compresse, per esempio lanciando java o javaw da un bat oppure lanciando il programma da Eclipse. è possibile scrivere del codice indipendente dal formato del bundle (jarrato o semplice ramo di directories) che carichi o decomprima (a seconda) le immagini dalla cartella gfx?
ps: lol, pamela.jpg :asd:
ecco, dimenticavo: non funziona perché la getResourceAsStream mi lancia una IllegalArgumentException che vorrei evitare di catturare perché non sarebbe codice indipendente dal formato del bundle :p
^TiGeRShArK^
23-10-2007, 12:53
ecco, dimenticavo: non funziona perché la getResourceAsStream mi lancia una IllegalArgumentException che vorrei evitare di catturare perché non sarebbe codice indipendente dal formato del bundle :p
:mbe:
ma vedi che quel codice funziona indipendentemente dal fatto che i tuoi files siano sentro un jar o no.
L?importante è che la struttura della directory sia visibile al tuo class loader.
Se ad esempio fai partire il tuo codice dalla directory classes e hai le risorse in una cartella resources è sufficiente che aggiungi al tuo classpath anche la cartella resources e tutto va a meraviglia ;)
P.S. e mi raccomando di non dimenticarti il disclaimer per impedire l'uso del tuo programma ai minori di anni 18 quando riesci finalmente a caricare il file pamela.jpg :O
:D
ARI-EDIT:
tanto per essere + chiaro in una situazione reale probabilmente hai questa situazione:
base-dir
| |
| |
classes resources
In quel caso se inserisci la directory basedir nel tuo classpath puoi accedere ai tuoi file usando il percorso "resources/gfx/pamela.jpg" che presumo manterrai anche nel tuo jar.
Altrimenti, se inserisci la cartella resources nel classpath al posto di base-dir, nel tuo jar devi omettere quella cartella e comprimere semplicemente la cartella gfx con tutto il suo contenuto (:oink: ) altrimenti quando andrai ad accedervi con il path "gfx/pamela.jpg" nel .jar ti ritrovi la directory resources nel mezzo e quindi ti sballa tutto :D
spero di essere stato un pò + chiaro ora :p
:mbe:
ma vedi che quel codice funziona indipendentemente dal fatto che i tuoi files siano sentro un jar o no.
L?importante è che la struttura della directory sia al di sopra di quella di partenza del tuo class loader.
Se ad esempio fai partire il tuo codice dalla directory classes e hai le risorse in una cartella resources è sufficiente che aggiungi al tuo classpath anche la cartella resources e tutto va a meraviglia ;) aaaaaaaah è vero, il cavolo di classpath! ora provo...
P.S. e mi raccomando di non dimenticarti il disclaimer per impedire l'uso del tuo programma ai minori di anni 18 quando riesci finalmente a caricare il file pamela.jpg :O
:D e ti pareva che andavamo avanti co sta cazzata :D :asd:
^TiGeRShArK^
23-10-2007, 13:02
aaaaaaaah è vero, il cavolo di classpath! ora provo...
dai un'occhio al mio edit successivo altrimenti tra 5 minuti torni a bestemmiare qui sul forum :asd:
dai un'occhio al mio edit successivo altrimenti tra 5 minuti torni a bestemmiare qui sul forum :asd: infatti stavo giusto scrivendo quando mi son visto spuntare il Gmail Notifier che mi avvisava della nuova risposta nella discussione sottoscritta :D (visto che organizzazione? :asd: )
comunque non capisco, dovrebbe essere tutto regolare ma non carica ste immagini... fammici sbattere ancora un po' e poi torno a bestemmiare :D
torno a bestemmiare :huh:
allora, io ho la cartella del mio progetto contenente le seguenti tre cartelle:
bin, contenente i .class
gfx, contenente le immagini
src, contenente i sorgenti .java
sapendo che voglio caricare le immagini in questo modo:
UnaMiaClasse.class.getResourceAsStream("/gfx/" + nomeFileImmagineConAncheEstensione);
quale classpath devo impostare in Eclipse? :mbe:
^TiGeRShArK^
23-10-2007, 13:44
torno a bestemmiare :huh:
allora, io ho la cartella del mio progetto contenente le seguenti tre cartelle:
bin, contenente i .class
gfx, contenente le immagini
src, contenente i sorgenti .java
sapendo che voglio caricare le immagini in questo modo:
UnaMiaClasse.class.getResourceAsStream("/gfx/" + nomeFileImmagineConAncheEstensione);
quale classpath devo impostare in Eclipse? :mbe:
".", ovvero la directory base del tuo progetto, come avevo scritto nell'edit :D
solo che mi sa che in eclipse non te lo fa fare così ad occhio :p
quindi creati una cartella resources in cui copi la tua cartella gfx e aggiungi resources al classpath :O
:D
ma veramente io vado dove mi permette di impostare i "VM arguments"... là posso scrivere qualunque cosa. ho provato a metterci:
-cp .
-cp ./
ma sinceramente mi sembrano un tantinello inutili... anche perché non va con nessuno dei due :muro:
^TiGeRShArK^
23-10-2007, 14:08
ma veramente io vado dove mi permette di impostare i "VM arguments"... là posso scrivere qualunque cosa. ho provato a metterci:
-cp .
-cp ./
ma sinceramente mi sembrano un tantinello inutili... anche perché non va con nessuno dei due :muro:
ho provato e se lo copi sotto resources o una qualche altra cartella e aggiungi quella al classpath funge perfettamente :p
public class ProvaLoad {
public ProvaLoad() {
InputStream inputStream = ProvaLoad.class.getResourceAsStream("/gfx/xxx/pam.jpg");
if(inputStream != null) {
System.out.println("non è null");
InputStreamReader isreader = new InputStreamReader(inputStream);
BufferedReader reader = new BufferedReader(isreader);
try {
System.out.println(reader.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
}
se passi l'opzione -cp . direttamente da eclipse sinceramente non so che effetto può avere dato che gli stai passando la directory base del suo progetto... e non ho idea se eclipse fa qualche controllo particolare, ma presumo di si dato che se provi ad aggiungere la directory stessa del progetto nel classpath ti bestemmia in aramaico e non te lo fa fare :p
quindi fai 'sta copia e non ti stressare :D
a dire il vero a me non funziona mica eh... :|
basta, ci rinuncio: quando faccio il debug me lo tengo senza icone, e le icone le vedrò solo nel jar finale. tanto ormai sto programma l'ho quasi finito :p
^TiGeRShArK^
23-10-2007, 14:20
a dire il vero a me non funziona mica eh... :|
basta, ci rinuncio: quando faccio il debug me lo tengo senza icone, e le icone le vedrò solo nel jar finale. tanto ormai sto programma l'ho quasi finito :p
ma come no cazz? :D
io l'ho fatto in 3 secondi e ho semplicemente aggiunto al classpath la cartella gfx e quindi accedevo ai file usando il percorso /xxx/pam.jpg
Nel caso in cui devi mantenere la cartella gfx nel percorso basta che crei una cartella resources, copi la tua cartella gfx li sotto e aggiungi la cartella resources nel classpath.
E poi controlli che il tuo codice sia quanto meno simile a quello che ho postato :p
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.