Aprire un File in Linguaggio C

Concetti Chiave
  • La funzione fopen è utilizzata per aprire un file in C.
  • La modalità di apertura del file può essere specificata come secondo argomento della funzione fopen.
  • La funzione restituisce un puntatore a un oggetto FILE che rappresenta il file aperto, oppure NULL se si è verificato un errore durante l'apertura del file.
  • È importante controllare il puntatore restituito da fopen per gestire eventuali errori di apertura del file.
  • La modalità di accesso specifica se il file deve essere aperto in lettura, scrittura o in modalità append. Inoltre, specifica se si tratta di un file di testo o di un file binario.

Apertura di un File

La funzione che la libreria standard del C mette a disposizione per aprire un file è la funzione fopen, che sta per file open. La sua firma è la seguente:

Definizione

Funzione fopen

#include <stdio.h>

FILE *fopen(const char * restrict filename,
            const char * restrict mode);

La funzione fopen richiede due parametri:

  1. filename: il nome del file da aprire (può includere il percorso).
  2. mode: la modalità di apertura del file (ad esempio, lettura, scrittura, ecc.).

Restituisce un puntatore a un oggetto FILE che rappresenta il file aperto, oppure NULL se si è verificato un errore durante l'apertura del file.

Il primo argomento della funzione fopen rappresenta una stringa che contiene il nome (il percorso o path più precisamente) del file da aprire. Il percorso contiene tutte le informazioni necessarie per localizzare il file nel file system, inclusi eventuali directory o sottodirectory. Esso può essere:

  • assoluto: specifica il percorso completo dalla radice del file system (ad esempio, /home/utente/documenti/file.txt).
  • relativo: specifica un percorso relativo alla directory di lavoro corrente (ad esempio, documenti/file.txt), dove per directory di lavoro corrente si intende la directory in cui si trova il programma in esecuzione.
Nota

Il parametro filename sotto Windows

Bisogna prestare particolare attenzione al parametro filename sotto il sistema operativo Windows.

Sotto Windows, i percorsi dei file utilizzano la barra rovesciata (\) come separatore di directory, mentre sotto Unix/Linux si utilizza la barra normale (/).

Tuttavia, nelle stringhe in linguaggio C la barra rovesciata, o backslash viene adoperata per indicare i caratteri di escape. Quindi, ad esempio, in un filename del genere:

C:\percorso\file.txt

Le due barre rovesciate verrebbero interpretate come inizio dei caratteri di escape (inesistenti tra l'altro) \p e \f.

Pertanto, se si specifica un percorso assoluto o relativo in un programma C destinato a essere eseguito su Windows, è necessario utilizzare il carattere di escape \\ che rappresenta la singola barra rovesciata. Ad esempio:

FILE *file = fopen("C:\\percorso\\file.txt", "r");

Nelle ultime versioni di Windows e di Visual Studio, per ovviare a questo problema è possibile utilizzare la barra normale (/) come separatore di directory, che viene interpretata correttamente anche nelle stringhe in linguaggio C. Ad esempio:

FILE *file = fopen("C:/percorso/file.txt", "r");

Il secondo argomento rappresenta una stringa che indica la modalità di accesso ossia si specifica quali operazioni si intendono effettuare sul file in questione. Un esempio è la modalità "r" che indica che il file deve essere aperto in modalità lettura. Vedremo nella prossima sezione le modalità in dettaglio.

Notiamo due dettagli fondamentali riguardanti i parametri della funzione fopen:

  • I parametri sono puntatori a char di tipo restrict:

    Questo significa che le due stringhe, filename e mode, non devono sovrapporsi in memoria.

  • Il parametro mode è un puntatore a char, ossia una stringa e non rappresenta un singolo carattere. Infatti esso può essere composto da una sequenza di caratteri.

La funzione fopen restituisce un puntatore a un oggetto FILE che rappresenta il file aperto, oppure NULL se si è verificato un errore durante l'apertura del file.

Tale puntatore deve essere salvato in una variabile per poi accedervi con altre funzioni nel resto del programma. Ad esempio:

FILE *file = fopen("esempio.txt", "r");

Le altre funzioni di accesso a file richiedono in ingresso il puntatore restituito da fopen. Le vedremo nelle prossime lezioni.

Di solito, quando fopen fallisce, ossia non riesce per vari motivi ad aprire il file, restituisce il valore NULL.

Nota

Controllare sempre il puntatore restituito da fopen

Non bisogna mai assumere che la chiamata a fopen abbia successo. Non è detto che un file possa essere aperto per una serie di motivi:

  • Il file potrebbe non esistere;
  • L'utente potrebbe non avere i permessi;
  • Il file potrebbe essere stato aperto da un altro programma.

Quindi bisogna sempre controllare il puntatore restituito da fopen prima di utilizzarlo. Ad esempio:

FILE *file = fopen("esempio.txt", "r");

if (file == NULL) {
    perror("Errore nell'apertura del file");
    return 1;
}

Modalità di Accesso ai File

Abbiamo detto che il secondo parametro della funzione fopen permette di specificare la modalità di accesso al file.

Attraverso questo parametro, però, non si specifica solo la modalità di accesso ma anche il tipo di file, ossia se il file che si sta andando ad aprire sia un file di testo o un file binario. Quindi, le modalità di accesso si dividono in due gruppi a seconda del tipo di file.

Se il file a cui si vuole accedere è un file di testo, il parametro mode può assumere uno dei seguenti valori:

Valore Descrizione Note
"r" Apertura in modalità lettura Il file deve già esistere
"w" Apertura in modalità scrittura partendo dall'inizio Non è necessario che il file esista. Se non esiste esso viene creato.
"a" Apertura in modalità scrittura (append) partendo dalla fine. Se il file non esiste, viene creato.
"r+" Apertura in modalità lettura e scrittura dall'inizio del file Il file deve già esistere.
"w+" Apertura in modalità lettura e scrittura partendo dall'inizio del file Se il file non esiste, viene creato. Se esiste, viene troncato.
"a+" Apertura in modalità lettura e scrittura partendo dalla fine del file Se il file non esiste, viene creato.
Tabella 1: Modalità di Accesso per File di Testo

Viceversa, se il file è un file binario, il parametro mode può assumere uno dei seguenti valori che sono simili ai precedenti ma in cui aggiungiamo una b:

Valore Descrizione Note
"rb" Apertura in modalità lettura Il file deve già esistere
"wb" Apertura in modalità scrittura partendo dall'inizio Non è necessario che il file esista. Se non esiste esso viene creato.
"ab" Apertura in modalità scrittura (append) partendo dalla fine. Se il file non esiste, viene creato.
"r+b" o "rb+" Apertura in modalità lettura e scrittura dall'inizio del file Il file deve già esistere.
"w+b" o "wb+" Apertura in modalità lettura e scrittura partendo dall'inizio del file Se il file non esiste, viene creato. Se esiste, viene troncato.
"a+b" o "ab+" Apertura in modalità lettura e scrittura partendo dalla fine del file Se il file non esiste, viene creato.
Tabella 2: Modalità di Accesso per File Binari

Come si può osservare dalle due tabelle di sopra, la libreria standard del C distingue la scrittura su file in due modalità: writing (scrittura) e append (scrittura in coda o aggiunta).

Quando si apre un file in modalità scrittura, normalmente il file viene troncato (truncated), ossia se il file esisteva già, il suo contenuto viene eliminato e il file viene riempito con nuovi dati a partire dall'inizio.

Viceversa, se si apre un file in modalità append, i dati vengono scritti alla fine del file preservando il vecchio contenuto; questo ovviamente se il file esisteva già. Per questo si parla di append o aggiunta.

Le modalità ibride di lettura/scrittura, invece, richiedono particolare attenzione. Non si può leggere prima e poi scrivere (o viceversa) senza gestire correttamente la posizione nel file. La posizione nel file rappresenta l'offset corrente da cui si legge o si scrive. Ritorneremo su questo concetto nelle prossime lezioni in cui lo studieremo in dettaglio.