PDA

View Full Version : [JAVA] percorso cercato dal jar


fefott
22-09-2006, 14:45
Avevo avuto un problema del genere anche un'altra volta ma questa volta non trovo una soluzione. Ora mi spiego...la prima volta,dopo aver creato il file jar del mio programma ho notato che non mi visualizzava le immagini perchè non trovava il percorso giusto dove pescarle. E' bastato modificare
Toolkit.getDefaultToolkit().getImage("images/GhostWest.gif");
in
Toolkit.getDefaultToolkit().getImage(LabyrinthPanel.class.getResource("images/GhostWest.gif");
e si è risolto tutto.

Ora ho lo stesso problema con la ricerca del percorso di un file e la chiamata da modificare è senz'altro questa:
private String url = "setting/scores.dat";
ObjectInputStream stream = new ObjectInputStream(new FileInputStream(url));
ma con cosa???

andbin
22-09-2006, 15:22
Ora ho lo stesso problema con la ricerca del percorso di un file e la chiamata da modificare è senz'altro questa:
private String url = "setting/scores.dat";
ObjectInputStream stream = new ObjectInputStream(new Scores.class.FileInputStream(url));
ma con cosa???URL url = Scores.class.getResource("setting/scores.dat");

Poi dal URL, ottieni un InputStream e .... leggi. ;)

fefott
22-09-2006, 15:35
Ho provato ma mi da errore...saresti così gentile da scrivermi esattamente quello che vuoi dire con <<Poi dal URL, ottieni un InputStream e .... leggi.>>
Nel senso che se utilizzo ObjectInputStream stream = new ObjectInputStream(new FileInputStream(url)); url deve essere una stringa e non un URL...ma mi sa che ho franiteso quello che mi hai scritto...

andbin
22-09-2006, 15:55
Ho provato ma mi da errore...saresti così gentile da scrivermi esattamente quello che vuoi dire con <<Poi dal URL, ottieni un InputStream e .... leggi.>>
Nel senso che se utilizzo ObjectInputStream stream = new ObjectInputStream(new FileInputStream(url)); url deve essere una stringa e non un URL...ma mi sa che ho franiteso quello che mi hai scritto...ObjectInputStream stream = new ObjectInputStream(url.openStream());

fefott
22-09-2006, 16:20
Perfetto..non mi da più errore ma...con questo lo leggo....
più avanti utilizzo
ObjectOutputStream stream = new ObjectOutputStream(new FileOutputStream(url));
per salvare....e questo con cosa lo sostituisco?? Naturalmente non posso usare openStream perchè serve per l'Input.

andbin
22-09-2006, 16:26
per salvare....e questo con cosa lo sostituisco?? Naturalmente non posso usare openStream perchè serve per l'Input.Allora ti conviene fare così:
URLConnection urlConn = url.openConnection();

ObjectInputStream streamInput = new ObjectInputStream(urlConn.getInputStream());

....

ObjectOutputStream streamOutput = new ObjectOutputStream(urlConn.getOutputStream());

fefott
22-09-2006, 16:51
Come non detto....sembrava funzionare ed invece non mi salva i nuovi valori...o meglio, sembra salvarli ma in realtà quando poi riavvio il gioco non ci sono..in sostanz deduco che non li abbia salvati nel file. Che faccio?? In compenso legge perfettamente.
Prima che mi venga chiesto non ci sono errori nella scrittura visto che senza il jar funziona alla perfezione (cioè eseguendolo dal main)...semplicemente non trova dove salvarlo.

TellaspallaBob
22-09-2006, 20:30
Il contenuto di un jar non lo modifichi così al volo.... soprattuto se poi questo è in sola lettura (e dovrebbe visto che è aperto dalla VM per eseguire il tuo programma)

Comunque devi passare per la classi del package Jar.

Vedi questo link che forse è meglio!!!
http://java.sun.com/j2se/1.4.2/docs/api/java/util/jar/package-summary.html

andbin
22-09-2006, 23:52
Come non detto....sembrava funzionare ed invece non mi salva i nuovi valori...o meglio, sembra salvarli ma in realtà quando poi riavvio il gioco non ci sono..in sostanz deduco che non li abbia salvati nel file. Che faccio?? In compenso legge perfettamente.Vero. :doh: Ti ho detto tutto ma mi son dimenticato che quel setting/scores.dat ce l'hai nel jar.
Come ha detto TellaspallaBob, non è così banale aggiornare un jar e comunque non in quel modo.

Però nota che se metti quella directory 'setting' al di fuori del jar (nella stessa directory dove risiede il jar), dovrebbe (uso il condizionale perché non ho mai provato) funzionare bene lo stesso. Ovviamente quel file scores.dat non sarebbe più contenuto nel jar. Ma è meglio così, dopotutto non vedo perché tu debba metterlo nel jar. ;)

fefott
23-09-2006, 15:44
Però nota che se metti quella directory 'setting' al di fuori del jar (nella stessa directory dove risiede il jar), dovrebbe (uso il condizionale perché non ho mai provato) funzionare bene lo stesso. Ovviamente quel file scores.dat non sarebbe più contenuto nel jar. Ma è meglio così, dopotutto non vedo perché tu debba metterlo nel jar. ;)

Ho provato e non funziona lo stesso...ad ogni modo mi serve che funzioni tutto dal jar poichè è l'unica cosa che devo consegnare al docente (naturalmente inserendo nel jar anche il sorgente)

TellaspallaBob
23-09-2006, 20:08
Per curiosità!!! Ma cosa stai cercando di salvare nel JAR???

Se usi ObjectOutputStrem si presume che tu voglia salvare una classe...
sei sicuro di averla resa serializzabile???

E poi usa il package JAR per gestire i file jar che poi sono l'estensione naturale del dello ZIP.

Ciao.

redcloud
25-10-2006, 17:08
Mi allaccio a questo thread perchè ho un problema analogo.

Da un file jar devo accedere a un file properties (file di testo) esterno al jar stesso.

La struttura del progetto è questa:


+ src
|
+ package
|
MyClass.java

+ config
|
FileProperties


Nel fil MyClass.java ho un'istruzione come questa

InputStream fileProperties = new FileInputStream("config" + File.separator + "FileProperties");

e se il progetto non lo esporto in un jar, funziona perfettamente. Nel momento in cui esporto solo i sorgenti in un file jar, il file non viene più trovato nel percorso. Come mai?

PGI-Bis
25-10-2006, 17:52
Il tuo "FileProperties" si trova in:

[directory di lavoro] + File.separator + "config" + File.separator + "FileProperties".

Forse la directory di lavoro usata quando lanci il jar non soddisfa la precondizione (che [directory di lavoro] coincida con la radice della cartella "config").

redcloud
25-10-2006, 18:08
Il tuo "FileProperties" si trova in:

[directory di lavoro] + File.separator + "config" + File.separator + "FileProperties".

Si. Quindi genero il jar e lo metto in [directory di lavoro] e da qui lo lancio ma nisba.

Sto impazzendo!

PGI-Bis
25-10-2006, 18:15
Qui ci vuole il metodo della nonna :D.

Prima di creare l'input stream, un bel:

File file = new File("config" + File.separator + "FileProperties");
System.out.println(file.getCanonicalPath());

e vedi un po' dove lo cerca, 'sto file.

redcloud
25-10-2006, 18:20
Qui ci vuole il metodo della nonna :D.

Prima di creare l'input stream, un bel:

File file = new File("config" + File.separator + "FileProperties");
System.out.println(file.getCanonicalPath());

e vedi un po' dove lo cerca, 'sto file.

Lo trova in

[root]\config\FileProperties

Magari prova tu a postare un esempio banale per controllare l'esistenza di un file e io mi ricavo i relativi percorsi.


EDIT: File("nomefile") non è adatto perchè crea il file se non esiste. Bisogna provare con FileInputStream perchè genera un'eccezione se il file non esiste.

EDIT 2: incredibile, ora va! Non so che ho fatto di diverso... grazie comunque!

EDIT 3 - EPILOGO: La storia è questa. Nella prima versione scrivevo correttamente il codice che funzionava sia esportando il sorgente in jar che non esportando. Il problema è sorto da linux perchè doppiocliccando sul file jar, esso lancia automaticamente il programma (come in windows) con la differenza però che la CWD non è la stessa dove risiede il file jar (e non so ancora perchè si comporti così). Questo mi ha portato a modificare tutti i possibili percorsi invano. Ripristinando il codice orignario, ho fatto le stesse prove da windows e doppiocliccando sul file jar, il file di testo viene trovato correttamente. In pratica il problema sta nel fatto che windows e linux trattano direttamente la CWD nel caso in cui si voglia lanciare il jar doppiocliccandolo :D (infatti se da linux lancio il file jar da riga di comando, tutto funziona alla perfezione).

PGI-Bis
25-10-2006, 19:02
[UN PS aggiunto in testa] stavo rispondendo quando è capitato il miracolo :D

Mhhhh... non ho capito. Comunque taglio la testa al toro.

Io uso nei miei programmi (non che siano tantissimi ma qualcuno c'è :D) un "getResource de noantri". Nel caso in questione stabilirei che la cartella "config" si debba trovare nella stessa cartella in cui si trova o il file jar che contiene le classi del programma o la radice del package a cui appartengono le classi del programma. Una cosa tipo:

+ cartella del programma/
+ Programma.jar
+ config/

Più in generale, una delle precondizioni è che il percorso di una risorsa esterna al programma sia determinabile a partire dalla cartella in cui si trova il file jar o la radice del package a cui appartengono le classi del programma. Potrebbe quindi essere anche:

+ cartella del programma/
+ bin/Programma.jar
+ config/

Premetto: è francamente inguardabile e "professionalmente" dovrei dirti di usare la cartella "user.home". Detto questo, il "getResource de noantri" che uso è fatto così:

package it.tukano.timebox;

import java.io.*;
import java.net.*;

/** Genera percorsi assoluti "esterni" a partire da percorsi relativi */
public class GeneratorePercorsi {

/** Genera un File il cui percorso assoluto è relativo alla cartella
in cui è presente la radice del package di questa classe. Ad esempio se
il file GeneratorePercorsi si trova nella cartella:
...\bongo\it\tukano\timebox\[GeneratorePercorsi.class]
il file prodotto sarà:
...\bongo\[path]
Se il file GeneratorePercorsi.class si trovi in un archivio Pacchetto.jar:
...\bongo\Pacchetto.jar
il file prodotto sarà:
...\bongo\[path]*/
public static File generaFile(String path) {
path = path.replace('\\', '/');
if(!path.startsWith("/")) path = "/" + path;
URL classPath =
GeneratorePercorsi.class.getResource("GeneratorePercorsi.class");
String basePath = classPath.toString();
if(isJar(classPath)) {
int index = basePath.indexOf("!");
for(int i = index; i > 0; i--) {
if(basePath.charAt(i) == '/') {
index = i;
break;
}
}
basePath = basePath.substring("jar:".length(), index + 1);
} else {
String fq = GeneratorePercorsi.class.getName().replace('.', '/');
fq += ".class";
basePath = basePath.substring(0, basePath.indexOf(fq) - 1);
}
try {
basePath = URLDecoder.decode(basePath, "UTF-8");
} catch(Exception ex) {
throw new RuntimeException(ex);
}
basePath = removeProtocol(basePath);
String filePath = basePath + path;
filePath = filePath.replace("/", File.separator);
return new File(filePath);
}

private static String removeProtocol(String path) {
return path.substring(("file:/").length(), path.length());
}

private static boolean isJar(URL r) {
return r.toString().indexOf("!") >= 0;
}
}

L'orrendo è probabilmente dovuto alla mia incapacità totale di accomiatarmi all'uso delle regular expressions: se c'è una cosa che so è che non le capiro MAI :D.

Ti incollo, per maggiore chiarezza, un caso d'uso di quella roba lì sopra. Ho un'applicazione per cui ho stabilito una disposizione dei file così fatta:

+ radice dell'applicazione
+ Modulo.jar //contiene il GeneratorePercorsi
+ configurazione/
+ configurazione/dbdescriptor.xml

Un certo oggetto dell'applicazione ottiene il file dbdescriptor.xml con:

public ProduttoreBaseDati() {
java.io.File file =
GeneratorePercorsi.generaFile("configurazione/dbdescriptor.xml");

Sinceramente non so se e quanto consigliarti una cosa del genere. A me serve perchè non ho una cartella user.home e l'applicazione anzichè essere installata viene replicata. Insomma, è peggio di un piccione viaggiatore e, sinceramente, non ho trovato un'idea migliore di questa :D.

redcloud
25-10-2006, 19:33
Grazie per l'impegno! La tua soluzione però è per un problema molto più complesso del mio...