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à | Lettura | Scrittura | Se il file esiste | Se non esiste | Parte da |
|---|---|---|---|---|---|
r | sì | no | lo apre | fallisce | inizio |
r+ | sì | sì | lo apre, mantiene il contenuto | fallisce | inizio |
w | no | sì | lo svuota | lo crea | inizio |
w+ | sì | sì | lo svuota | lo crea | inizio |
a | no | sì | mantiene il contenuto | lo crea | fine, ogni scrittura si accoda |
a+ | sì | sì | mantiene il contenuto | lo crea | fine, ogni scrittura si accoda |
x | no | sì | fallisce | lo crea | inizio |
x+ | sì | sì | fallisce | lo crea | inizio |
c | no | sì | mantiene il contenuto | lo crea | inizio |
c+ | sì | sì | mantiene il contenuto | lo crea | inizio |
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.