Dopo aver analizzato le funzioni che consentono le operazioni di base sui file, in questa guida vediamo quelle per effettuare operazioni più complesse come ad esempio copiare, rinominare ed eliminare un file, ottenere informazioni su un file e le funzioni per la gestione di cartelle.
Come già sappiamo, per poter lavorare con un file abbiamo bisogno di:
fopen()
, che ci restituisce il puntatore al file.fclose()
utilizzando il suo puntatore.Indice dei contenuti
PHP mette a disposizione la funzione copy()
per effettuare la copia di un file. Può essere utilizzata per fare piccole copie di backup ad intervalli di tempo prestabiliti.
La funzione accetta due argomenti di tipo stringa che fanno riferimento rispettivamente al percorso del file di origine e a quello di destinazione.
Nel seguente script di esempio, la funzione copia il file file.txt
che si trova nella directory corrente nella posizione indicata in $newFile
, restituendo false
in caso di errore.
<?php
$file = 'file.txt';
$newFile = 'file-copied.txt';
if (false === copy($file, $newFile)) {
printf("Impossibile copiare il file %s", $file);
}
Nota: Se avessi voluto copiare il file di origine verso una directory diversa da quella corrente, avremmo dovuto specificare un valore diverso in $newFile come ad esempio "directory/file-copied.txt".
L'operazione di spostamento di un file, ossia quella che di solito eseguiamo tramite le combinazioni di tasti Ctrl + X (Copia) e Ctrl + V (Incolla), è possibile effettuarla tramite la funzione rename()
, che come suggerisce il nome consente di rinominare un file.
La funzione prende in input il nome del file da rinominare ritornando true
in caso di successo, false
altrimenti.
<?php
$oldFile = '/old-path/image.jpg';
$newFile = '/new-path/new-image.jpg';
if (false === rename($oldFile, $newFile)) {
printf('Impossibile rinominare il file %s', $oldPath);
}
La funzione unlink()
consente di eliminare un file in maniera permanente dal file system. La funzione prende un singolo parametro, il nome del file che si vuole cancellare.
<?php
$file = 'file.txt';
if (false === unlink($file)) {
printf("Impossibile eliminare il file %s", $file);
}
Le funzioni PHP viste fino ad ora potrebbero generare messaggi di errore, dovuti solitamente al fatto che il file sul quale vogliamo operare non esiste.
Non è insolito infatti imbattersi in un avviso simile al seguente
PHP Warning: fopen(file.txt): failed to open stream: No such file or directory in...
Per verificare se un file esiste o meno, il linguaggio mette a disposizione la funzione file_exists()
che, preso il nome del file ne verifica l'esistenza restituendo true
oppure false
.
Riprendendo l'esempio relativo alla cancellazione di un file, per rendere il codice più robusto possiamo scrivere quanto segue
<?php
$file = 'file.txt';
if (false === file_exists($file)) {
printf("Il file %s non esiste", $file);
exit;
}
if (false === unlink($file)) {
printf("Impossibile eliminare il file %s", $file);
}
Lo script termina stampando a video un errore se il file non esiste, altrimenti prosegue con l'operazione di cancellazione vera e propria.
I file contengono diverse informazioni riguardo se stessi, ad esempio la dimensione, la data di ultima modifica, l'id del proprietario.
Possiamo recuperare queste informazioni tramite la funzione stat()
che prende il nome del file come parametro e restituisce un array contenente statistiche e informazioni sul file, elencate nella seguente tabella
Indice numerico | Indice associativo | Informazioni |
---|---|---|
0 | dev | Numero del dispositivo |
1 | ino | Numero dell'inode |
2 | mode | Modalità di protezione dell'inode |
3 | nlink | Numero di collegamenti |
4 | uid | ID utente del proprietario |
5 | gid | ID di gruppo del proprietario |
6 | rdev | Tipo del dispositivo, se dispositivo inode |
7 | size | Dimensioni in byte |
8 | atime | Data dell'ultimo accesso |
9 | mtime | Data dell'ultima modifica |
10 | ctime | Data dell'ultimo cambiamento |
11 | blksize | Dimensioni dei blocchi per l'I/O del file system |
12 | blocks | Numero di blocchi allocati |
Un esempio di output della funzione stat()
eseguita su sistema operativo Linux
<?php
$stats = stat('robots.txt');
print_r($stats);
/* Output
Array
(
[0] => 2050
[1] => 6951840
[2] => 33204
[3] => 1
[4] => 1004
[5] => 1005
[6] => 0
[7] => 25
[8] => 1572203082
[9] => 1568766637
[10] => 1572203082
[11] => 4096
[12] => 8
[dev] => 2050
[ino] => 6951840
[mode] => 33204
[nlink] => 1
[uid] => 1004
[gid] => 1005
[rdev] => 0
[size] => 25
[atime] => 1572203082
[mtime] => 1568766637
[ctime] => 1572203082
[blksize] => 4096
[blocks] => 8
)
*/
Nota: non tutte le informazioni richiamabili tramite la funzione stat()
sono disponibili in tutti i sistemi operativi. Ad esempio, in Windows non saranno disponibili l'ID utente e l'ID di gruppo perché, a differenza di Linux, Windows non fornisce tali informazioni.
Esistono anche alcune funzioni specifiche per ricavare le proprietà correlate al tempo, che restituiscono valori nel formato Unix timestamp:
fileatime()
restituisce l'ora in cui il file ha ricevuto l'ultimo accesso, o false
in caso di errore.filectime()
restituisce l'ora in cui il file è stato cambiato l'ultima volta, o false
in caso di errore. Un file viene considerato come cambiato se viene creato o scritto o quando sono stati cambiati i suoi permessi.filemtime()
restituisce l'ora in cui il file è stato modificato l'ultima volta, o false
in caso di errore. Un file viene considerato come modificato se viene creato o i suoi contenuti sono cambiati.La funzione filemtime()
in particola si rivela molto utile per forzare l'aggiornamento di un foglio di stile di un sito web che ha subito una modifica recente.
Infatti, nella realizzazione di un sito web si è soliti memorizzare nella cache del browser risorse statiche come CSS, JS in maniera tale che i successivi accessi al sito siano più veloci. Tuttavia una eventuale modifica a uno di questi file statici non verrebbe visualizzata dall'utente che ha già visitato quel sito.
La soluzione è quella di modificare il nome del file per forzare l'aggiornamento della cache. Per fare ciò possiamo sfruttare filemtime()
in questo modo
<link rel="stylesheet" href="/assets/css/amdesk.css?ver=<?php echo filemtime('/assets/css/amdesk.css')">
che produce un output simile a questo
<link rel="stylesheet" href="/assets/css/amdesk.css?ver=1574506234">
Usata in combinazione con la funzione feof()
che restituisce true
quando viene raggiunta la fine di un file, la funzione fgetc()
può essere utilizzata per leggere un carattere alla volta da un file.
La funzione accetta come argomento il puntatore al file e restituisce un solo carattere dal file a cui fa riferimento.
Di seguito è mostrato un esempio di funzionamento
<?php
$file = 'file.txt';
$handler = fopen($file, 'r');
while (!feof($handler)) {
$char = fgetc($handler);
echo $char."\n";
}
fclose($handler);
La funzione fgetc()
é tanto semplice da usare quanto scomoda se abbiamo a che fare con file di grandi dimensioni, poiché leggendo un carattere per volta, è necessario un tempo molto lungo per leggere tutto il file.
Per fortuna PHP mette a disposizione la funzione fgets()
, che consente di leggere intere righe di caratteri.
La funzione fgets()
accetta due parametri: il puntatore al file e il parametro $lenght
, restituendo una stringa di lunghezza massima in byte pari a $lenght
- 1.
La lettura termina quando:
<?php
$handler = fopen("file.txt", "r");
if (false !== $handler) {
while (false !== ($buffer = fgets($handler, 4096))) {
echo $buffer;
}
if (!feof($handler)) {
echo "Errore nella lettura tramite fgets()\n";
}
fclose($handler);
}
Le funzioni viste fino ad ora consentono di leggere i dati in modo sequenziale, cioè nello stesso ordine in cui sono disposti nel file.
Questa modalità di lettura crea una limitazione: quando l'indicatore di posizione del file supera un determinato punto, per tornare a leggere prima di quel punto è necessario chiudere e riaprire il file.
PHP offre la possibilità di posizionarsi in un punto qualsiasi all'interno di un file tramite la funzione fseek()
, la cui sintassi è la seguente
fseek ( resource $handle , int $offset [, int $whence = SEEK_SET ] ) : int
dove:
$handle
è il puntatore al file$offset
è la nuova posizione corrente (in byte)$whence
è la posizione da cui iniziare a leggereLa funzioni restituisce 0
in caso di successo, -1
altrimenti. I possibili valori di $whence
sono rappresentati da 3 costanti
SEEK_SET
: l'inizio del file (default)SEEK_CUR
: posizione correnteSEEK_END
: fine del fileNota: la funzione fseek()
è comoda nei casi in cui sappiamo a priori come è stato costruito il file che dobbiamo leggere (ad esempio con le righe aventi lunghezza 10 caratteri).
Facciamo un esempio per chiarire meglio il funzionamento di fseek()
<?php
$filename = 'file.txt';
$offset = 35;
$handler = fopen($filename, 'w+');
if (false !== $handler) {
for ($i = 1; $i < 10; $i++) {
fwrite($handler, "Riga $i\n");
}
fseek($handler, $offset);
$buffer = fread($handler, 1024);
}
fclose($handler);
echo $buffer;
Tramite un ciclo for scriviamo 9 volte una stringa di lunghezza fissa all'interno di un file, successivamente spostiamo l'indicatore di posizione avanti di 35 byte (riga 11), dunque la lettura successiva (riga 12) tramite fread()
comincerà da "Riga 6" fino al termine.
Vediamo ora un set di funzioni per manipolare le directory. Alcune di queste utilizzano un descrittore di directory, mentre altre utilizzano una stringa che rappresenta il nome della directory.
Un descrittore di directory è molto simile a un descrittore di file, ossia un numero intero che punta a una directory.
La prima funzione che andiamo a presentare è mkdir()
che consente di creare una cartella, specificandone il nome come parametro
$dirname = 'php';
if (false === mkdir($dirname)) {
printf('Impossibile creare la directory %s', $dirname);
}
Se l'operazione è andata a buon fine, la funzione restituisce true
.
Così come è possibile creare una directory, allo stesso modo la si può eliminare.
Per cancellare una directory dal file system è necessario utilizzare la funzione rmdir()
<?php
$dirname = 'php';
if (false === rmdir($dirname)) {
printf('Impossibile eliminare la directory %s', $dirname);
}
Per leggere il contenuto di una cartella è necessario inanzitutto farsi ritornare il puntatore alla directory. La funzione preposta a tale operazione è opendir()
.
Una volta che abbiamo il puntatore alla directory, possiamo utilizzare la funzione readdir()
per leggere, un file alla volta, il contenuto della directory.
L'elenco delle voci ritornate da readdir()
include pure .
(che specifica la directory corrente) e ..
(che specifica il genitore della directory corrente).
Alla fine dell'operazione di lettura possiamo rilasciare le risorse tramite la funzione closedir()
.
<?php
$handler = opendir('php-7');
if (false !== $handler) {
while ($file = readdir($handler)) {
echo $file."\n";
}
}
closedir($handler);
Concludiamo questa guida con la funzione per rinominare una cartella che poi è la stessa utilizzata per rinominare i file, ossia rename()
<?php
$dirname = 'php-5';
if (false === rename($dirname, 'php-7')) {
printf('Impossibile rinominare la directory %s', $dirname);
}
La lista completa sulle funzioni per gestire il file system è disponibile a questo indirizzo.
Nelle prossime guide vedremo invece come gestire i file CSV, JSON e XML.