Contenuto del capitolo |
---|
|
Le operazioni sui file spesso costituiscono per i principianti un problema, anche se non riesco a spiegarmi perché. I file dal punto di vista della programmazione non sono affatto differenti da quelli che si usano con un programma di elaborazione di testi o con un'altra applicazione: devono essere aperti (open, N.d.t.), poi è possibile fare le operazioni e infine devono essere chiusi (close, N.d.t.).
La differenza maggiore consiste nel fatto che da un programma l'accesso avviene in modo sequenziale, cioè si legge una linea alla volta a partire dall'inizio. In pratica l'elaboratore di testi spesso si comporta allo stesso modo, solo che scrive l'intero file in memoria mentre lo si usa e lo riscrive completamente al termine, quando viene chiuso. Un'altra differenza consiste nel fatto che normalmente il file viene aperto o in sola lettura o in sola scrittura. Si può scrivere in un file creandone uno nuovo (o sovrascrivendo uno già esistente) oppure appendendo linee ad un file esistente.
Un'altra cosa che può essere fatta con un file durante il suo uso è tornare all'inizio.
prosciutto e uova prosciutto e patatine prosciutto e prosciutto
Adesso scriveremo un programma che legge il file e ne visualizza il contenuto, come il comando 'cat' di Unix o 'type' del DOS.
# Prima apriamo il file in lettura (r) inp = open("menu.txt","r") # Si trasferisce il contenuto del file in una lista # e poi si scrive ogni elemento di questa for linea in inp.readlines(): print linea # Adesso il file viene chiuso inp.close()
Nota 1: open() richiede due argomenti. Il primo è il nome del file (che può essere passato coma una variabile oppure come una costante di tipo stringa, come abbiamo fatto nell'esempio). Il secondo è il modo. Il modo stabilisce se stiamo aprendo il file per leggere (r) o per scrivere (w), e anche se il file contiene testo ASCII o dati di tipo binario - aggiungendo in questo caso una 'b' ad 'r' o a 'w', ad esempio: open(fn,"rb")
Nota 2: Abbiamo letto e chiuso il file usando funzioni precedute dalla variabile relativa al file. Questa notazione viene detta chiamata di metodo ed è un primo esempio di programmazione ad oggetti. Per il momento non ce ne preoccupiamo se non per capire che è in qualche modo collegata ai moduli. Possiamo pensare la variabile collegata al file come un riferimento ad un modulo che contiene le funzioni per le operazioni sui file e che viene importato automaticamente ogni volta che creiamo una variabile di tipo file.
Vediamo come possiamo trattare i file lunghi. Innanzitutto sarà necessario leggere il file una linea alla volta (in Python si usa la funzione readline() invece di readlines()). Si può quindi usare una variabile NumeroLinee che viene incrementata ad ogni linea e verificata ogni volta per vedere se è uguale a 25 (per un schermo a 25 linee). Quando è uguale si chiede all'utilizzatore di premere un tasto (ad esempio invio) prima di rimettere NumeroLinee a zero e proseguire. Potreste provare a realizzare il programma per esercizio...
In effetti non c'è altro. Si apre un file, lo si legge, e poi lo si manipola in qualunque modo desiderato. Al termine si chiude il file. Per creare un comando 'copy' (copia, N.d.t.) in Python semplicemente apriamo un nuovo file in scrittura e scriviamo le linee su tale file invece che scriverle sullo schermo. Ad esempio:
# Creare l'equivalente del comando: COPY MENU.TXT MENU.BAK # Prima di tutto si aprono i file in lettura e scrittura inp = open("menu.txt","r") outp = open("menu.bak","w") # si legge il file in una lista e si copia # nel file nuovo for line in inp.readlines(): outp.write(line) print "copiato 1 file..." # Adesso si chiudono i file inp.close() outp.close()
Come avrete notato abbiamo aggiunto una istruzione print al solo scopo di assicurare all'utilizzatore che è effettivamente accaduto qualcosa. Usare questo tipo di messaggi di controllo è sempre una buona idea.
E per finire un'altra variante: supponiamo che vogliate appendere dati ad un file già esistente. Un modo per farlo potrebbe essere aprire il file in lettura, leggere i dati nella lista, appendere altri dati alla lista ed infine scrivere l'intera lista nel file di uscita che diventa una nuova versione del file precedente. Se il file è corto questo procedimento funziona perfettamente ma se il file è molto lungo, diciamo maggiore di 100 Mbyte, finireste per non avere abbastanza memoria per contenere la lista. Fortunatamente esiste il modo "a" che possiamo usare nella funzione open() che ci consente di appendere direttamente ad un file esistente semplicemente con l'istruzione write(). Anzi meglio, se il file non esiste sarà creato proprio come se avessimo usato il modo "W".
Ad esempio supponiamo di avere un file "log" da utilizzare per raccogliere messaggi di errore. Non vogliamo che i messaggi di errore che già contiene siano cancellati, quindi decidiamo di appendere il nuovo messaggio di errore nel modo seguente:
def logErrori(msg): err = open("Errori.log","a") err.write(msg) err.close()
In una vera applicazione probabilmente sarebbe necessario limitare in qualche modo la dimensione del file. Una tecnica molto comune consiste nel creare un nome di file basato sulla data, cosí quando la data cambia automaticamente verrà creato un nuovo file ed in questo modo risulta semplice per l'amministratore del sistema trovare l'errore avvenuto in un dato giorno ed archiviare i file degli errori dei giorni passati se non servono più.
Riprendiamo ora il programma di conteggio delle parole visto in un precedente capitolo. Ricordiamo che lo pseudocodice era il seguente:
def n_parole(s): lista = split(s) # lista i cui elementi sono le parole return len(lista) # restituisce il numero di elementi della lista for linea in file: totale = totale + n_parole(linea) # somma i totali per ogni linea print "Il file contiene %d parole" % totale
Adesso che sappiamo come leggere le linee del file consideriamo il corpo della funzione n_parole(). Prima di tutto vogliamo creare una lista contenente tutte le parole di una linea. Se cerchiamo nella documentazione di Python il modulo string troviamo una funzione di nome "split" che divide una stringa in una lista di campi separati da spazi bianchi (o altri caratteri specificati). Cercando ulteriormente nella documentazione troviamo anche la funzione di base len() che riporta il numero di elementi di una lista, che nel nostro caso è il numero di parole nella linea - proprio ciò che vogliamo.
Quindi il codice definitivo è:
import string def n_parole(s): lista = string.split(s) # È necessario specificare il modulo contenete split return len(lista) # restituisce il numero di elementi della lista inp = open("menu.txt","r") totale = 0 # imposta inzialmente a zero; viene anche creata la variabile for linea in inp.readlines(): totale = totale + n_parole(linea) # somma i totali per ogni linea print "Il file contiene %d parole" % totale inp.close()
Il programma non è ancora del tutto corretto perché ad esempio conta il carattere '&' come una parola (magari potrebbe essere giusto ...). Inoltre può essere usato solo su un unico file (menu.txt). Però non è poi molto difficile modificarlo in modo che possa leggere il nome del file dalla linea di comando (argv[1] o tramite la funzione raw_input()) come abbiamo gia visto nel capitolo "Conversazione con l'utilizzatore". Lasciamo questa modifica come esercizio per il lettore.
Anche il BASIC ed il Tcl forniscono i mezzi per trattare i file. Non sono molto diversi dal Python in questo, quindi mostreremo solo il programma 'cat' realizzato con i due linguaggi.
Il BASIC utilizza un concetto detto stream (sequenza, N.d.t.) per indicare i file. Le stream in BASIC sono numerate e questa cosa può rendere macchinoso il loro uso. Per semplificarlo è possibile usare una utile funzione chiamata FREEFILE che riporta il prossimo numero libero usabile come stream. Se lo memorizzate in una variabile non è più necessario dover ricordare quale numero è associato a ciascuna stream o file.
INFILE = FREEFILE
OPEN "TEST.DAT" FOR INPUT AS INFILE
REM Verifica la fine del file (EOF) e poi
REM Leggi una linea dal file e scrivila
DO WHILE NOT EOF(INFILE)
LINE INPUT #INFILE, Linea
PRINT Linea
CLOSE #INFILE
Adesso il meccanismo dovrebbe essere chiaro. Ecco la versione in Tcl:
set infile [open "Test.dat" r] while { [gets $infile linea] >= 0} { puts $linea } close $infile
Promemoria |
---|
|
Precedente  Successivo  Indice
Se avete domande o suggerimenti relativi a questa pagina
mandate un e-mail all'autore:
alan.gauld@yahoo.co.uk
o al traduttore italiano:
lfini@arcetri.astro.it