Indice del libro


Quando un programma termina, le informazioni contenute nei suoi dati vanno perse. Per conservare delle informazioni tra un'esecuzione e un'altra di un programma o per passare dei dati da un programma ad un altro, si usano i file. Un file è una sequenza di informazioni scritte su un supporto di memoria permanente. La classe file permette di leggere, scrivere e modificare file.

File di testo

modifica

Per scrivere stringhe in un file di testo basta aprire il file in scrittura e usare il suo metodo write. Terminato di scrivere nel file basta chiuderlo e questo è disponibile per altre applicazioni.

fo=file('prova.txt', 'w')
fo.write('Primo file di testo:\n\n')
fo.write('terza riga,\n')
fo.write('quarta riga riga,\n')
fo.write('fine del file.')
fo.close()

Leggere un file è altrettanto semplice: aprire il file in lettura, leggere le righe scorrendo il file come una sequenza:

for riga in file('prova.txt'):
    print riga,

Se vogliamo salvare in un file dei dati numerici possiamo tradurli in stringhe e salvarli come stringhe. Ad es. creiamo una matrice di numeri interi:

def randmat(dr, dc, massimo):
    import random
    m=[[random.randrange(massimo) for c in xrange(dc)] for r in xrange(dr)]
    return m

matrice=randmat(5, 4, 100)

possiamo salvare la matrice in un file usando le seguenti istruzioni:

def salvamat(matrice, nomefile):
    fo=file(nomefile, 'w')
    for riga in matrice:
        riga=[str(val) for val in riga]
        fo.write('\t'.join(riga)+'\n')
    fo.close()

salvamat(matrice, 'matrice.txt')

Una funzione che legga la matrice dal file e costruisca una lista di liste è:

def leggimat(nomefile):
    fi=file(nomefile)
    m=[[int(e) for e in riga.split('\t')] for riga in fi]
    fi.close()
    return m

E infine qualche riga di codice controlla che lettura e scrittura siano avvenute correttamente.

print matrice
matriceletta=leggimat('matrice.txt')
if matrice==matriceletta:
    print 'Salvataggio e lettura effettuati con successo'
else:
    print 'La matrice salvata e quella letta sono diverse!'
    print 'quella letta è:'
    print matriceletta

File binari

modifica

Un file binario contiene dati che non sono organizzati in stringhe di caratteri ma è semplicemente una sequenza di byte. Per interpretare un file binario bisogna conoscerne la struttura. Supponiamo di avere un file che contiene 5 stringhe pascal lunghe 20, 20, 1, 2 e 46 caratteri. Ogni stringa pascal ha inoltre un carattere, posto all'inizio, che indica la lunghezza della stringa. Il file dunque è organizzato in blocchi di 94 caratteri:

 

Per estrarre i dati e tradurlo in un file di testo con i campi separati da virgole, devo leggere tutti i blocchi che compongono il file, interpretarli e scrivere i dati ottenuti in un file di testo. Per aprire in lettura il file binario di nome "CL2PI" si usa il comando:

fi=file("CL2PI", 'rb')

Per leggere un blocco di 94 caratteri sotto forma di sequenza di byte:

r=fi.read(94)

ora ci serve una funzione che legga i 5 campi presenti nel record e ce li restituisca come tupla di sstringhe:

def estrairecord(r):
    """Riceve una riga e la traduce in base alle specifiche."""
    return (estrai_stringa_pascal(r, 0),
            estrai_stringa_pascal(r, 21),
            estrai_stringa_pascal(r, 42),
            estrai_stringa_pascal(r, 44),
            estrai_stringa_pascal(r, 47),
           )


E una funzione che data la posizione del primo carattere di una stringa pascal, quello che ne fornisce la lunghezza, estragga la stringa:

def estrai_stringa_pascal(s, i):
    """Estrae dalla stringa s la sottostringa che inizia in i e che ha
       come primo byte la lunghezza, secondo la codifica del Pascal."""
    ls=ord(s[i])
    return s[i+1:i+ls+1]

Il programma può essere completato con la funzione che legge il file binario e scrive un file di testo:

def estraidati(nomefilein, nomefileout):
    """Traduce il file di ingresso e scrive il file di uscita."""
    fi=file(nomefilein, 'rb')
    fo=file(nomefileout, 'w')
    while True:
        r=fi.read(94)
        if r:
            print estrairecord(r), '\n'
            fo.write(','.join(estrairecord(r))+'\n')
        else:
            break
    fo.close()

estraidati('CL2PNI', 'CL2PNI.txt')