Newsgroup: it.comp.java
Titolo: Apertura di un file .gz

Salve a tutti,
dovrei leggere dei file di testo compressi con estensione .gz ma non so
esattamente come fare...finora infatti li avevo scompattati e avevo
creato una classe di lettura che estraesse i dati dentro il file nella
maniera a me più congeniale. Tuttavia ho constatato che i file sono
moltissimi e ognuno è zippato(se fosse stata solo la cartella nn credo
sarebbe stato un grosso problema) e quando lo decomprimo aumenta molto
le sue dimensioni. La cosa migliore da fare sarebbe decomprimerlo,
leggerlo e restiturimi i risultati, senza che però il file decompresso
rimanga nell'hard disk, ossia che rimanga .gz. In rete avevo trovato
un'istruzione del tipo:
DataInputStream dis = new DataInputStream(new GZIPInputStream(new
FileInputStream("prv.Gz")));
che vorrei usare per modificare il seguente pezzo del mio programma:
File file = new File(filename.toString());
ReadNextGenFile results = new ReadNextGenFile(file);
dove quest'ultima istruzione richiama la seguente classe di lettura, di
cui riporto le parti principali:
//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());
        }
Avevo provato a scrivere qualcosa del tipo:
DataInputStream file = new DataInputStream(new GZIPInputStream(new
FileInputStream(filename.toString())));
ReadNextGenFile results = new ReadNextGenFile(file);
Non appena faccio questo eclipse mi segnala di modificare i parametri
del costruttore della classe ReadNextGenFile , passando da string a
datainputstream, ma così facendo nn funziona più nulla perchè il
metodo che ho scritto dopo il costruttore andrebbe modificato, ma nn ho
idea di come operare (nn ho dimestichezza con la lettura da file).
Infatti non so come combinare il tutto con la classe scanner, che usa
il metodo getabsolutepath della classe file.
Spero che il problema sia chiaro, vi ringrazio anticipatamente per le
eventuali risposte.

 esattamente come fare...
Estrai i file uno per uno in una directory temporanea, leggi il file
corrente e cancellalo. Non caricare i file in memoria, a meno che non
sia strettamente necessario
Enrico

 writes:
A> try {
A>   GZIPInputStream gzs = new GZIPInputStream(new
A> FileInputStream(GZFile));
A>   byte[] buf = new byte[gzs.available()];
A>   File tmpFile = File.createTempFile("prova", ".txt");
A>   FileOutputStream fos = new FileOutputStream(tmpFile);
A>   int c;
A>   while ((c = gzs.read(buf)) != -1) {
A>     fos.write(buf);
A>   }
A>   fos.flush();
A>   fos.close();
A> }
A> catch (Exception e) {
A>   e.printStackTrace();
A> }
Se non si ha molta  memoria, meglio usare il temporaneo, ma ovviamente
ci mette il tempo che serve a decomprimere il file.
Ah, il blocco catch() fatto in questo modo non è la scelta migliore.
Al tuo  amico che  conosce java consiglia  di rileggersi i  javadoc di
GZIPInputStream :)
-- 
 /\           ___
/___/\_|_|\_|__|___Gian Uberto Lauri_____
  //--\| | \|  |   Integralista GNUslamico
\/                 e coltivatore diretto di Software


^___^   mi era infatti sembrato strano...
Cmq sono riuscita a risolvere il problema... mi è bastato cancellare
qualcosina e sostituire DataInputStream al posto di file e tutto fila,
senza bisongo di creare file temporanei &Co. che fanno solo perdere
molto più tempo e memoria!!!

 molto più tempo e memoria!!!
Dipende dai punti di vista. Se hai un file di testo di pochi Kb e lo
carichi interamente in memoria, allora hai ragione. Ma se il file e`
gia` superiore ai 500Kb, allora incomincerei a rivalutare il discorso
"file temporanei" (no, il discorso "Ma tanto al giorno d'oggi abbiamo
quintali di RAM" non regge)
Enrico

 quintali di RAM" non regge)
Sei sicuro che sia meglio? I miei file gz erano di 300Mb circa ma se li
decomprimo diventano di 2.3 MB a testa. Aprendoli con DataInputstream
impiega più o meno quanto impiegava a leggergli quando erano zippati,
se devo creare un file temporaneo invece, ci impiega moltissimo tempo
in più (al momento non saprei quantificare). Cosiderando che nel mio
programma apro centinaia di questi file (se non migliaia), immagina
quanto impiegherebbe il programma a girare! Devo solo capire se una
volta letto rimane tutto in memoria o mi estrae quello che voglio e il
file si chiude...

 file si chiude...
normalmente se fai un close() sull' InputStream il file viene chiuso e
la memoria liberata.
Cmq se il file deve venire letto solo una volta allra scompattarlo in
una cartella temporanea fa perdere tempo.
Diverso se il file viene aperto all'inizio e rimane aperto per tutta
l'esecuzione del programma (vuoi perche' ci continui a leggere o a
scrivere), allora in questo caso scompattarlo in una directory
temporanea, lavorarci su, e poi alla fine ricompattarlo e' meglio,
perche' non ti tiene occupata la memoria (ma chiaramente e' piu' lento
che mantenere il file in RAM), e inoltre in caso di crash del sistema
rischi di poter recuperare il file temporaneo (e se e' un file su cui
salvi roba recuperi il lavoro fatto).
Ciao Jack

> molto più tempo e memoria!!!
E'B> Dipende dai punti di vista. Se hai un file di testo di pochi Kb e
E'B> lo carichi interamente in memoria, allora hai ragione.
Sei certissimo che gli InflaterInputStream carichino TUTTO in memoria ?
A me pareva che decomprimessero al volo. 
E'B> (no, il discorso "Ma tanto al
E'B> giorno d'oggi abbiamo quintali di RAM" non regge)
Ci  sarebbe  sempre lo  swap.  Lasci fare  l'IO  per  blocchi in  modo
efficente al sistema :).


 A me pareva che decomprimessero al volo. 
Se il file devo solo decomprimerlo, allora probabilmente hai ragione. Se
il file devo decomprimerlo _e_ successivamente leggerlo (cosa che, se
non ho capito male, e` l'operazione che deve fare l'OP), allora o lo
tengo in memoria  o lo scrivo su file e successivamente lo leggo a
blocchi
Enrico

> memoria ?  A me pareva che decomprimessero al volo.
E'B> Se il file devo solo decomprimerlo, allora probabilmente hai
E'B> ragione. Se il file devo decomprimerlo _e_ successivamente
E'B> leggerlo (cosa che, se non ho capito male, e` l'operazione che
E'B> deve fare l'OP),
Non mi pare che lo legga  in memoria per leggerlo, ma lo decomprima on
demand, anche se lo leggi.
L'impronta in memoria di questo programma
import java.util.zip.GZIPInputStream;
import java.io.FileInputStream;
import java.io.File;
/**
 * Describe class Ziprova here.
 *
 *
 * Created: Wed Dec 13 09:29:00 2006
 *
 * @author <a href="mailto:
sa...@eng.it
">Gian Uberto Lauri</a>
 * @version $Revision$
 */
public class Ziprova {
	/**
	 * Crea una nuova istanza di <code>Ziprova</code> .
	 *
	 */
	public Ziprova() {
	}
	/**
	 * <code>main</code>
	 *
	 * @param args a <code>String[]</code>
	 */
	public static final void main(final String[] args)
		throws Exception{
		GZIPInputStream gizzy = new GZIPInputStream(
			new FileInputStream(
				new File(args[0])
				)
			);
		int letto = gizzy.read();
		while( letto != -1) {
			System.out.print(".");
			letto = gizzy.read();
 
		}
	}
}
non cambia, stando a top, usando uno o l'altro di questi due file:
-rw-r--r--  1 saint saint 3611598 Sep 25 10:31 ../jhove-1_0.tar.gz
-rw-r--r--  1 saint saint   27495 May 10  2006 ../html-helper-mode_3.0.4kilo.tar.gz
Quindi te lo  carichi tutto in memoria solo se  lo vuoi leggere tutto,
altrimenti te lo leggi un pezzetto alla volta.
// Ma tu non eri un fan di python ? :)


 altrimenti te lo leggi un pezzetto alla volta.
Ehm, forse mi sono spiegato male in quello che intendevo. Con la
stringa di codice:
GZIPInputStream gizzy = new GZIPInputStream(new FileInputStream(new
File(args[0])));
leggo il file .gz . Dopodiche`, questo file devo decomprimerlo. Una
volta decompresso ho n file txt che devo prima caricare in memoria e poi
leggerlo. Se il file .gz contiene una moltitudine di file, e` ovvio che
se li carico tutti in memoria mi ci vorra` tanta ram quanto e`
l'occupazione decompressa dei file. Spero di essermi spiegato meglio
Enrico

 // Ma tu non eri un fan di python ? :)
Io con Java ci lavoro :)
Per quanto riguarda Python, personalmente sono indeciso se portarne
avanti lo studio oppure concentrarmi su qualcos'altro
Enrico

 Se il file .gz contiene una moltitudine di file,
Non è  :). Solo gli  ZIP sono anche  archivi :). Ma anche  con quelli,
lavori su una sola parte alla volta.
