Newsgroup: it.comp.java
Titolo: Aprire una diretory e poi un file

Ciao a tutti,
il problema è il seguente. Ho una directory principale in cui ho
memorizzate delle sottodirectory con all'interno un numero di file
variabile. Devo nel mio programma selezionare una data directory in
base al suo nome e un determinato file in questa directory, sembre in
base al suo nome. Questa operazione deve essere utilizzabile per tutti
i file e le cartelle della mia directory principale.
Domanda: non avendo mai fatto (a parte una volta) stream di file, come
dovrei secondo voi organizzare il tutto? Quali argomenti converrebbe
andare a guardare? Cerco di spiegarmi meglio:
La mia sottodirectory si chiama x53z08, un'altra x59z06, ecc ecc.; in
base ad un ciclo for in cui ottengo, ad esempio x=53 e z=08 seleziono
(non ho idea di come) la prima. Dentro questa ho numerosi file,
chiamati m04x53z08, m05x53z08 e in base ad un altro ciclo ottengo m=05
e seleziono questo secondo file(e anche qui non so come).
Conviene lavorare con una variabile string e quando il mio valore è
uguale seleziono quello che mi interessa?
Si accettano suggerimenti, link a siti, ecc ecc...
Grazie

 writes:
A> Ciao a tutti, il problema è il seguente. Ho una directory
A> principale in cui ho memorizzate delle sottodirectory con
A> all'interno un numero di file variabile. Devo nel mio programma
A> selezionare una data directory in base al suo nome e un determinato
A> file in questa directory, sembre in base al suo nome.
La classe  che ti  serve è  java.io.File, di cui  ti invito  a leggere
attentamente la descrizione.
La classe  File riprende un  po' (tanto) l'idea  di Unix che  anche le
directory  sono  (particolari)  file  -  per le  directory  il  metodo
isDirectory ritorna true.
Datti un occhio al metodo listFiles() che a naso ti torna utile.
Un'ultimo consiglio. Se devi costruire stringhe (String) non usare
questo meccanismo:
a = b + c + d + e
ma preferisci 
StringBuffer t = new StringBuffer(b);
t.append(c);
t.append(d);
t.append(e);
a=t.toString();
Gli  oggetti String  sono immutabili,  e l'operatore  + agisce  su due
parametri.
Questo vuole dire che viene creata  una stringa per b+c, una per b+c+d
ed  una per  il  risultato  finale. Ciascuna  di  queste viene  creata
usando, se non ricordo male, uno StringBuffer creato al volo...
-- 
 /\           ___
/___/\_|_|\_|__|___Gian Uberto Lauri_____
  //--\| | \|  |   Integralista GNUslamico
\/                 e coltivatore diretto di Software

 StringBuffer t = new StringBuffer(b);
Ancor meglio StringBuilder se stai usando Java5 e non hai a che fare
con Thread

> StringBuffer t = new StringBuffer(b);
p> Ancor meglio StringBuilder se stai usando Java5 e non hai a che
p> fare con Thread
Indubbiamente,  quando non serve  la sincronizzazione  è una  palla al
piede.
E nel caso di Angela mi pare che si lavori già con la 1.5



Grazie tanto per la risposta, ricordi bene, uso la 1.5. Magari quando
ho un attimo di tempo provo a dare un'occhiata alla classe File e
magari vi faccio sapere se ci sono novità...
Se trovate ottimi link (anche in inglese con un pò di pazienza li
leggo) che spiegano come fare un'operazione del genere postateli pure.
ciao a tutti e grazie

 
Io sono sempre un tifoso del tutorial della Sun, a suo tempo mi ha dato 
parecchie soddisfazioni.
http://java.sun.com/docs/books/tutorial/essential/io/fileio.html
e in generale
http://java.sun.com/docs/books/tutorial/
bye
DKano

Posto il nuovo problema che si è venuto a creare...
Il metodo che mi avete suggerito voi è perfetto ma...praticamente non
so come modificare una cosina, che magari è banale... Io ho scritto
qualcosa del tipo:
StringBuilder filename = null;
filename = new StringBuilder("/mydir/a0o2/x");
filename.append("53z");
filename.append(met);
filename.append("/m");
filename.append(mas);
filename.append("x53z");
filename.append(met);
filename.append(".track2");
quello che viene fuori è qualcosa del tipo:
/mydir/a0o2/x53z0.8/m1.4x53z0.8.track2
ma in realtà dovrei avere:
/mydir/a0o2/x53z08/m14x53z08.track2
cioè, siccome met e mas sono dei double, e quindi con la virgola, mi
aggiunge pure il punto. Come potrei correggere questa cosa? Una volta
sistemato ciò il mio file è pronto per essere letto ed elaborato come
voglio io(spero!).
Grazie a chiunque mi dia una risposta...

 writes:
A> cioč, siccome met e mas sono dei double, e quindi con la virgola,
A> mi aggiunge pure il punto. Come potrei correggere questa cosa? Una
A> volta sistemato ciň il mio file č pronto per essere letto ed
A> elaborato come voglio io(spero!).  Grazie a chiunque mi dia una
A> risposta...
Trattali come stringhe.
La piu` semplice e` convertire  i double separatamente e poi eliminare
i blank a colpi di index() e replace().
Un'altra  sarebbe  moltiplicare  per  10  i numeri  fintanto  che  non
diventano interi, ma rimarrei sulla prima...
In bocca al lupo (o in .... alla balena, non so come si usa da voi)


 In bocca al lupo (o in .... alla balena, non so come si usa da voi)
Si usano entrambi! ^__^

 va:
Tutto risolto... banalmente scrivevo:
 a.replace(".", "");
anzichè: 
a= a.replace(".", "");

> nn va:
A> Tutto risolto... banalmente scrivevo:
A>  a.replace(".", "");
A> anzichè:
A> a= a.replace(".", "");
Capita  e  peraltro  ritornare  la  stringa modificata  è  una  scelta
obbligata. E` uno dei motivi per cui preferisco fare fare
// Calcola someOperator su a e b
static Sometype someOperator(Sometype a, Sometype b)
piuttosto che 
// Calcola someOperator su this e b ritornando il valore (non
// modificando this che rimane inalterato) 
Sometype someOperator(Sometype b)


Grazie tanto per il suggerimento... invece ho un altro piccolo dubbio
che non so risolvere al momento, o meglio sto ancora pensando a come
fare... Praticamente ho dei file nominati così:
\mydir\lte59-2.0-0.0.spec che dovrei aprire . Il problema è che io
dispongo solo del primo numero (e forse anche del secondo, ma dovrei
vedere) che lì compare (in questo caso 59, ma ho visto che vanno da 20
a 100). In realtà questo numero è stato abbreviato, quindi anzichè
59 è 5900 e dai miei calcoli invece viene fuori qualcosa del tipo
5944.554047704027
Avevo pensato che si potrebbe arrotondare, convertire il stringa e
prendere solo i primi due numeri (quindi 59 e se ho a disposizione
anche -2.0 ), poi, non so come, dovrei confrontare il nome del mio file
verificando che questo valore compare e sceglierlo. Avevo provato,
guardando in rete, a cercare di fare una cosa simile. L'unica cosa che
sono riuscita a trovare è la seguente:
File dir = new File ( "/mydir/" ) ;
File[] Files = dir.listFiles ( );
for ( int i = 0 ; i < Files.length ; i ++ ) {
 if ( Files[i].isDirectory ( ) )
        System.out.println ( "Directory: " + Files[i] ) ;
 else if ( Files[i].isFile ( ) )
        System.out.println ( "File: " + Files[i] ) ;
 }
Qualche altro suggerimento su come operare? Grazie mille!!!

 writes:
A> Praticamente ho dei file nominati così:
A> \mydir\lte59-2.0-0.0.spec che dovrei aprire . 
Sono i soli file in quella directory ? 
Il tuo problema è:
- Ho una directory piena di roba tra cui alcuni file che mi servono e
  che hanno il nome fatto così e cosà
oppure
- Ho una directory con dei file fatti così e cosà e devo aprirli in
  un certo ordine
oppure
- A partire da un certo numero devo trovare in una directory il file
  il cui nome corrisponde a quel numero
o è ancora uno diverso ?
Sinceramente, al momento ho più problemi a capire che ti serve che a
determinare posizione e velocità di un elettrone... :)
A> Il problema è che io
A> dispongo solo del primo numero (e forse anche del secondo, ma
A> dovrei vedere) che lì compare (in questo caso 59, ma ho visto che
A> vanno da 20 a 100). In realtà questo numero è stato abbreviato,
A> quindi anzichè 59 è 5900 e dai miei calcoli invece viene fuori
A> qualcosa del tipo 5944.554047704027 Avevo pensato che si potrebbe
A> arrotondare, convertire il stringa e prendere solo i primi due
A> numeri
La cosa  giusta da fare è  sapere esattamente come  vengono generati i
nomi dei file.
Quindi,  a parer  mio, serve  cercare  di individuare  le parti  fisse
(sicuramente quelle parti ci sono nel nome del file), quelle variabili
(i numeri  che determini) ed eventuali parti  indeterminate (parti che
vengono generate come gli gira).
Da queste  puoi provare  a costruirti una  regexp formata  dalle varie
parti,  quelle fisse  e  variabili che  entrano  come literal,  quelle
ideterminate  come ".*"  e poi  usare quella  per identificare  i file
partendo dal nome e che non sono directory.



Per regexp intendi una espressione? Non ne avevo mai sentito parlare
(sarà che il mio libro è proprio da principianti!)

> nomi dei file.
A> Nel mio file lte59-2.0-0.0.spec 59 (che posi sarebbe 5900) , 2.0 e
A> 0.0 sono dei valori che ritrovo all'interno del file stesso e che
A> lo caratterizzano univocamente. Dai file che avevo aperto nei miei
A> post precedenti ricavo in pratica solo il primo numero e l'ultimo
A> (cioè 0.0), l'unico che non conosco è il secondo (cioè 2.0).
Hmm, una  espressione regolare a  questo punto potrebbe  essere (ocio,
non  testata e  non  verificate  per la  sintassi  usata dalla  classe
Pattern.
"lte"[1º numero]"-"[0-9]+(\.[0-9]+)?"-"[2º numero]".spec"
                   ~~~~~~^^^^^^^^^^^
Dove le  parti tra doppi apici sono  così come sono, [xº  numero] è un
numero fornito da te e la parte in mezzo, se non ho fatto cavolate, fa
il match con una sequenza di almeno una cifra seguita opzionalmente da
un punto ed una seconda sequenza di almeno una cifra.
A> Per regexp intendi una espressione? Non ne avevo mai sentito parlare
Non sono cose facillime, e tendono ad essere di sola scrittura.
Ti consiglio di cercare prima un tutorial sulle "espressioni regolari"
o  "regular expressions"  o  "regexp", dopodiché  guardarti le  classi
Pattern e Matcher.


                    ~~~~~~^^^^^^^^^^^
Ora vedo se la posso applicare...però spulciando tra i miei file ho
notato che possono cambiare un pochino forma, soprattutto se l'ultimo
numero nn è 0.0, cioè ho qualcosa del tipo:
lte59-5.5+0.5.alpha=+0.6.spec
Quindi, quelllo che avevo pensato di fare io era la seguente cosa, ma
nn so se è possibile farla:
costruire una sorta di stringa dove ho "lte59-****0.6.spec", faccio una
lista dei file nella mia directory e quelli che hanno inizio e fine
uguale alla mia stringa li scelgo...si può fare?

 writes:
A> Quindi, quelllo che avevo pensato di fare io era la seguente cosa,
A> ma nn so se è possibile farla: costruire una sorta di stringa dove
A> ho "lte59-****0.6.spec", faccio una lista dei file nella mia
A> directory e quelli che hanno inizio e fine uguale alla mia stringa
A> li scelgo...si può fare?
Si fa così:
lte59-.*0\.6\.spec
:)


Ho provato a scrivere qualcosa del tipo:
StringBuilder filename = new
StringBuilder("/mydir/lte"+Temp+"-"+"*.*0.6.spec" );
 File dir = new File ( "/mydir/" ) ;
 File[] Files = dir.listFiles ( );
 for ( int i = 0 ; i < Files.length ; i ++ ) {
        if ( Files[i].equals(filename))
		 System.out.println ( "File: " + Files[i] ) ;
		 }
ma evidentemente non lo vede...poi mi sorge un altro dubbio. Qualora
trovasse un file col nome simile, visto che in questo caso Files è un
oggetto, come lo passo alla classe file per farglielo leggere? appena
ci provo spuntano 10000 errori!

 writes:
A> ma evidentemente non lo vede...poi mi sorge un altro dubbio. Qualora
A> trovasse un file col nome simile, visto che in questo caso Files è
A> un oggetto, come lo passo alla classe file per farglielo leggere?
A> appena ci provo spuntano 10000 errori!
No che non lo vede. File non supporte le wildcard.
Ti devi tirare  su tutti i file della directory,  e poi analizzarne il
nome per vedere se  va bene e metterti da parte il  o i File che vanno
bene.
La regexp indicata serviva a fare il match sul nome del file: se fa il
match ti va bene.


  File[] Files = dir.listFiles ( );
 >>>>>>>>>>>>>>>>>>>>>>>^^^^^^^^^^
e' qui che devi filtrare i files che ti interessano. listFiles() ti 
permette di fornire una classe filtro in modo che solo i file che 
ritieni validi vengono accettati e ritornano in Files (a proposito i 
nomi delle variabili in java č meglio che siano in minuscolo, quindi
File[] files, non File[] Files.
bye
DKano

Grazie per i suggerimenti, ma al momento accantono quest'utlimo
progetto(devo prima parlane col mio prof, magari si semplifica), ma ho
un altro problema al momento. Avrei bisogno di leggere dei file
zippati...
Infatti quest'ultimo file che dovevo leggere era zippato, così come
tutti gli altri, e mi sembra un'assurdità doverli unzippare ad uno ad
uno, considerando che per ogni cartella sono centinaia. Mi pare di aver
capito che questa operazione in java si può fare, ma ancora nn ho
capito benissimo come e soprattutto se il file rimane unzippato
insieme a quello .gz o se lo zippa solo per leggerlo ma rimane
inalterato. Dalla rete ho beccato questa istruzioncina qui (che nn ho
ancora ben capito se fa al caso mio):
DataInputStream dis = new DataInputStream(new GZIPInputStream(new
FileInputStream("prv.Gz")));
ora, se al posto di "prv.Gz" scrivo filename.toString() se lo becca
ma...ho un problema!
Infatti prima facevo qualcosa del tipo:
File file = new File(filename.toString());
ReadNextGenFile results = new ReadNextGenFile(file);
dove questultima era una classe apposita che mi leggeva il mio file.
Adesso però, non essendo molto pratica di stream & Co. , quando provo
a scirvere:
DataInputStream file = new DataInputStream(new GZIPInputStream(new
FileInputStream(filename.toString())));
ReadNextGenFile results = new ReadNextGenFile(file);
compare un errore in quest'ultima riga. Ho pensato che sia dovuto al
fatto che nella mia classe di vettura vada cambiato qualche pezzo
(riporto i passi che eclipse mi segnala):
//costruttore
public ReadNextGenFile(String stringFile) {
	try {
		Scanner sc = new Scanner(new File(stringFile));
....
                } catch (Exception e) {
			e.printStackTrace();
		}
	}
	public ReadNextGenFile(File file) {
		this(file.getAbsolutePath());
	}
Credo si debba convertire String in DataInputStream, cosa che a me nn
convince, perchè se ci provo non funziona più niente. Probabilemnte
sto mescolando metodi di classi diverse...
Qualche idea???

 writes:
A> Dalla rete ho
A> beccato questa istruzioncina qui (che nn ho ancora ben capito se fa
A> al caso mio):
A> DataInputStream dis = new DataInputStream(new GZIPInputStream(new
A> FileInputStream("prv.Gz")));
Corretto.  Se riesci  a mettere  le  mani su  una copia  di Core  Java
spiegano come funziona l'implementazione dell'I/O.
A> ora, se al posto di "prv.Gz" scrivo filename.toString() se lo becca
A> ma...ho un problema!
A> Infatti prima facevo qualcosa del tipo: File file = new
A> File(filename.toString()); ReadNextGenFile results = new
A> ReadNextGenFile(file);
Attenzione. Un  File è una modellazione dell'oggetto  del file system,
per  leggerlo   devi  usare   un  reader  o   uno  stream,   cosa  che
ReadNextGenFile() faceva.
Devi modificare  il metodo in  modo che riceva uno  InputStream invece
che un File.
