C/Lettura e scrittura su file: differenze tra le versioni

Wikibooks, manuali e libri di testo liberi.
< C
Contenuto cancellato Contenuto aggiunto
Riga 56: Riga 56:
|-
|-
|b||se una b viene aggiunta alle modalità precedenti si indica che il file è binario. Ossia:
|b||se una b viene aggiunta alle modalità precedenti si indica che il file è binario. Ossia:
rb, wb, ab, e r+b, w+a, a+b equivalenti a rb+, wb+, ab+
rb, wb, ab, e r+b, w+b, a+b equivalenti a rb+, wb+, ab+
|}
|}

== Flussi standard ==
== Flussi standard ==
Ci sono tre flussi di file che risultano aperti in modo predefinito, all'avvio del programma:
Ci sono tre flussi di file che risultano aperti in modo predefinito, all'avvio del programma:

Versione delle 16:24, 2 dic 2010

Indice del libro

Dal punto di vista del programma scritto in linguaggio C, il file viene utilizzato in qualità di flusso logico di dati (stream), ovvero flusso di file. Per la precisione, un file viene aperto attribuendogli un puntatore che rappresenta il flusso di file relativo; quando poi il flusso viene chiuso, l'associazione con il file si conclude.

La gestione del flusso di file avviene in modo trasparente, con l'ausilio di funzioni standard e una struttura dati definita nella libreria stdio si tratta del tipo 'FILE'.

L'apertura di un file, attraverso le funzioni standard, coincide con l'ottenimento di un puntatore al tipo FILE; pertanto, questo puntatore rappresenta il flusso di file e tutti i riferimenti a tale flusso si fanno con quel puntatore.

Apertura e chiusura di un file

L'apertura dei file viene ottenuta normalmente con la funzione fopen() che restituisce il puntatore al file, oppure il puntatore nullo, NULL, in caso di fallimento dell'operazione. L'esempio seguente mostra l'apertura del file mio_file contenuto nella directory corrente, con una modalità di accesso in sola lettura.

#include <stdio.h>
...
int main (void)
  {
    FILE *fp_mio_file;
    ...
    fp_mio_file = fopen ("mio_file", "r");
    ...
  }

Come si vede dall'esempio, è normale assegnare il puntatore ottenuto a una variabile adatta, che da quel momento identifica il file, finché questo resta aperto.

La chiusura del file avviene in modo analogo, attraverso la funzione fclose(), che restituisce zero se l'operazione è stata conclusa con successo, oppure il valore rappresentato da EOF. L'esempio seguente ne mostra l'utilizzo.

...
    fclose (fp_mio_file);
...

La chiusura del file conclude l'attività con questo, dopo avere scritto tutti i dati eventualmente ancora rimasti in sospeso (se il file è stato aperto in scrittura).

I prototipi delle 2 funzioni:

 FILE* fopen (const char *nome, const char *modalità);

 int fclose (FILE *flusso_di_file);

Il parametro nome rappresenta il percorso del file da aprire, mentre la modalità è una delle seguenti:

Modalità Significato
r file di testo in sola lettura.
w file di testo in sola scrittura. Se esiste ne è cancellato il contenuto altrimenti viene creato
r+ file di testo in lettura e scrittura.
w+ Se il file non esiste, lo crea e lo apre in lettura e scrittura. Se esiste, lo cancella e lo apre in lettura e scrittura.
a Apre il file in sola scrittura, facendo in modo che si possa solo aggiungervi del contenuto, alla fine. Se il file non esiste, viene creato.
a+ Come a, solo che è abilitata anche la lettura.
b se una b viene aggiunta alle modalità precedenti si indica che il file è binario. Ossia:

rb, wb, ab, e r+b, w+b, a+b equivalenti a rb+, wb+, ab+

Flussi standard

Ci sono tre flussi di file che risultano aperti in modo predefinito, all'avvio del programma:

  • standard input, corrispondente normalmente alla tastiera;
  • standard output, corrispondente normalmente allo schermo del terminale;
  • standard error, anch'esso corrispondente normalmente allo schermo del terminale.

Spesso si utilizzano questi flussi di file attraverso funzioni apposite che vi fanno riferimento in modo implicito, ma si potrebbe accedere anche attraverso funzioni generalizzate, utilizzando come puntatori i nomi: stdin, stdout e stderr.

File di testo

I file di testo possono essere gestiti in modo più semplice attraverso due funzioni: fgets() e fputs(). Queste permettono rispettivamente di leggere e scrivere un file una riga alla volta, intendendo come riga una porzione di testo che termina con il codice di interruzione di riga, secondo l'astrazione usata dal linguaggio.

La funzione fgets() permette di leggere una riga di testo di una data dimensione massima. Si osservi l'esempio seguente:

...
fgets (ca, 100, fp);
...

In questo caso, viene letta una riga di testo di una dimensione massima di 99 caratteri, dal file rappresentato dal puntatore fp. Questa riga viene posta all'interno dell'array ca, con l'aggiunta di un carattere \0 finale. Questo fatto spiega il motivo per il quale il secondo parametro corrisponde a 100, mentre la dimensione massima della riga letta è di 99 caratteri. In pratica, l'array di destinazione è sempre una stringa, terminata correttamente.

Nello stesso modo funziona fputs(), che però richiede solo la stringa e il puntatore del file da scrivere. Dal momento che una stringa contiene già l'informazione della sua lunghezza perché possiede un carattere di conclusione, non è prevista l'indicazione della quantità di elementi da scrivere.

...
fputs (ca, fp);
...

Seguono i modelli sintattici delle funzioni fputs() e fgets(), in forma di prototipi di funzione:

char *fgets (char *stringa, int dimensione_max, FILE *stream);
int fputs (const char *stringa, FILE *stream);

Se l'operazione di lettura riesce, fgets() restituisce un puntatore corrispondente alla stessa stringa (cioè l'array di caratteri di destinazione), altrimenti restituisce il puntatore nullo, NULL, per esempio quando è già stata raggiunta la fine del file.

La funzione fputs() permette di scrivere una stringa in un file di testo. La stringa viene scritta senza il codice di terminazione finale, \0, ma anche senza aggiungere il codice di interruzione di riga. Il valore restituito è un valore positivo in caso si successo, altrimenti EOF.