Menu

PHP fopen(): aprire, leggere e scrivere file (le modalità)

fopen('data.txt', 'r') apre un file e restituisce un handle, oppure false in caso di errore. Leggi dall'handle con fgets() o fread(), scrivi con fwrite(), chiudilo con fclose(). La modalità ('r', 'w', 'a', 'x', 'c' e le loro forme con +) decide cosa puoi fare.

Questa pagina include editor eseguibili: modifica, esegui e vedi subito l'output.

fopen('data.txt', 'r') apre un file e restituisce un handle, una risorsa stream che le altre funzioni sui file accettano come primo argomento. Leggi con fgets() (una riga) o fread() (un certo numero di byte), scrivi con fwrite() e chiudi con fclose(). Il secondo argomento è la modalità: 'r' per leggere, 'w' per scrivere, 'a' per aggiungere in fondo.

Output:

Got: apple
Got: banana
Got: cherry

fopen() restituisce false quando non riesce ad aprire il file (non esiste in modalità r, manca una cartella, mancano i permessi), e PHP stampa un warning come:

Warning: fopen(missing.txt): Failed to open stream: No such file or directory in /home/index.php on line 2

Quindi verifica false prima di usare l'handle. Per leggere o scrivere un intero file piccolo in una sola chiamata, file_get_contents() e file_put_contents() sono più brevi; fopen() serve per i file che leggi a pezzi o tieni aperti.

Modalità di fopen

ModalitàLetturaScritturaSe il file esisteSe non esisteParte da
rsìnolo aprefallisceinizio
r+sìsìlo apre, mantiene il contenutofallisceinizio
wnosìlo svuotalo creainizio
w+sìsìlo svuotalo creainizio
anosìmantiene il contenutolo creafine, ogni scrittura si accoda
a+sìsìmantiene il contenutolo creafine, ogni scrittura si accoda
xnosìfalliscelo creainizio
x+sìsìfalliscelo creainizio
cnosìmantiene il contenutolo creainizio
c+sìsìmantiene il contenutolo creainizio

Due righe sorprendono. r+ scrive sopra i byte esistenti sul posto, senza inserire, e a+ scrive sempre alla fine, anche dopo aver spostato il puntatore con fseek() (spostarlo influisce solo sulle letture):

Output:

Xbc
Xbc
Xbc
end

Su Windows potresti vedere 'rb' o 'wb': il flag b significa binario e impedisce a Windows di tradurre i fine riga. Su Linux e macOS non fa nulla, quindi aggiungerlo è innocuo e portabile.

Leggere un file riga per riga con fgets()

fgets() restituisce la riga successiva compreso il suo \n, e false alla fine del file. Dato che in memoria c'è una sola riga alla volta, questo ciclo gestisce un file di log di qualsiasi dimensione, e puoi fermarti prima con break:

Output:

2 errors in 5 lines
line 2: database timeout
line 4: disk full

Confronta con false usando !==, non con un semplice while ($line = fgets($fh)): una riga che contiene solo "0" senza a capo (l'ultima riga di un file può esserlo) è falsy e terminerebbe il ciclo in anticipo.

Scrivere e aggiungere con fwrite()

fwrite() scrive una stringa nella posizione corrente e restituisce il numero di byte scritti, oppure false in caso di errore. fputs() è la stessa funzione con un altro nome. Apri con 'a' per aggiungere in fondo a un file senza toccare ciò che c'è:

Output:

wrote 12 bytes
wrote 13 bytes
wrote 15 bytes
visit /home
visit /about
visit /contact
visit /home

PHP_EOL è il fine riga del sistema su cui gira PHP (\n su Linux e macOS, \r\n su Windows). Per i file letti da altri programmi, scegline uno esplicitamente, di solito "\n".

Leggere e scrivere file CSV con fgetcsv() e fputcsv()

fputcsv() scrive un array come una riga CSV e mette tra virgolette i campi che contengono virgole, virgolette o a capo. fgetcsv() rilegge una riga come array. Passa esplicitamente il separatore, il carattere di delimitazione e un carattere di escape vuoto: così ottieni un CSV standard, e PHP 8.4 stampa un avviso di deprecazione quando l'argomento di escape viene omesso.

Output:

name,city,note
Ada,London,"likes ""math"", a lot"
Linus,Helsinki,kernel

Ada lives in London: likes "math", a lot
Linus lives in Helsinki: kernel

Dividere le righe con explode(',', $line) si rompe appena un campo contiene una virgola; fgetcsv() gestisce le virgolette per te. Per un file separato da punti e virgola (comune nelle esportazioni Excel in Europa), passa ';' come separatore.

Muoversi in un file con fseek(), ftell() e rewind()

Un file aperto ha una posizione. Letture e scritture partono da lì e la fanno avanzare. ftell() ti dice dove si trova, fseek() la sposta a un offset in byte, e rewind() torna all'inizio. Con w+ puoi scrivere un file e rileggerlo tramite lo stesso handle:

Output:

11
world
hello world

Bloccare un file con flock()

Due richieste che leggono un contatore, aggiungono uno e lo riscrivono nello stesso momento possono leggere entrambe 41 e scrivere entrambe 42. flock() con LOCK_EX fa aspettare la seconda finché la prima non rilascia il lock. Qui la modalità giusta è c+: crea il file se serve e, a differenza di w+, non lo svuota prima che tu abbia il lock.

Output:

Visitor number 1
Visitor number 2
Visitor number 3

I lock sono consultivi: fermano solo altro codice che chiama anch'esso flock(). Per aggiungere una riga, file_put_contents($path, $line, FILE_APPEND | LOCK_EX) fa lo stesso in una chiamata.

Errore comune: while (!feof($fh))

Molti vecchi tutorial usano un ciclo con feof(). Restituisce true solo dopo che una lettura ha già raggiunto la fine, quindi il ciclo gira una volta in più rispetto alle righe e l'ultimo fgets() restituisce false:

Output:

string(2) "a
"
string(2) "b
"
string(2) "c
"
bool(false)
4 rounds for 3 lines

Quel false in più diventa una riga vuota in un report o un elemento vuoto in un array. Fai il ciclo sulla lettura stessa, while (($line = fgets($fh)) !== false), come fanno tutti gli altri esempi di questa pagina.

Domande frequenti

Quali sono le modalità di fopen in PHP?

r legge, w scrive dopo aver svuotato il file, a scrive in fondo, x crea un nuovo file e fallisce se esiste, e c scrive senza svuotarlo. Aggiungere + (r+, w+, a+, x+, c+) permette sia di leggere sia di scrivere. Ogni modalità tranne r e r+ crea il file quando manca.

Qual è la differenza tra w e a in fopen?

w svuota il file appena viene aperto e scrive dall'inizio. a mantiene il contenuto e ogni fwrite() va alla fine del file, anche dopo fseek(), il che la rende la modalità per i file di log.

Come leggo un file CSV in PHP?

Aprilo con fopen($path, 'r') e chiama fgetcsv() in un ciclo: while (($row = fgetcsv($fh, null, ',', '"', '')) !== false) { ... }. Ogni chiamata restituisce una riga come array di campi, con virgolette e virgole interne gestite per te.

Devo chiamare fclose in PHP?

PHP chiude ogni file aperto quando lo script termina, quindi uno script breve funziona anche senza. Chiama comunque fclose() appena hai finito: scarica le scritture in buffer, rilascia i lock presi con flock() e impedisce a uno script di lunga durata di esaurire gli handle dei file.

Illustrazione dei linguaggi di programmazione di Coddy

Impara a programmare con Coddy

INIZIA