PHP
Gestione dei file
Ricerca…
Sintassi
- int readfile (string $ filename [, bool $ use_include_path = false [, resource $ context]])
Parametri
Parametro | Descrizione |
---|---|
nome del file | Il nome del file viene letto. |
use_include_path | È possibile utilizzare il secondo parametro opzionale e impostarlo su TRUE, se si desidera cercare il file anche in include_path. |
contesto | Una risorsa di flusso di contesto. |
Osservazioni
Sintassi del nome file
La maggior parte dei nomi di file passati a funzioni in questo argomento sono:
- Archi in natura.
- I nomi dei file possono essere passati direttamente. Se vengono passati i valori di altri tipi, vengono convertiti in stringa. Questo è particolarmente utile con
SplFileInfo
, che è il valoreSplFileInfo
diDirectoryIterator
.
- I nomi dei file possono essere passati direttamente. Se vengono passati i valori di altri tipi, vengono convertiti in stringa. Questo è particolarmente utile con
- Relativo o assoluto.
- Possono essere assoluti. Sui sistemi Unix, i percorsi assoluti iniziano con
/
, ad esempio/home/user/file.txt
, mentre su Windows i percorsi assoluti iniziano con l'unità, ad es.C:/Users/user/file.txt
- Possono anche essere relativi, che dipende dal valore di
getcwd
e soggetti a modifiche da parte dichdir
.
- Possono essere assoluti. Sui sistemi Unix, i percorsi assoluti iniziano con
- Accetta i protocolli.
- Possono iniziare con
scheme://
per specificare il wrapper del protocollo con cui gestire. Ad esempio,file_get_contents("http://example.com")
recupera il contenuto da http://example.com .
- Possono iniziare con
- Slash-compatibili.
- Mentre il
DIRECTORY_SEPARATOR
su Windows è una barra rovesciata e il sistema restituisce i backslash per i percorsi per impostazione predefinita, lo sviluppatore può ancora usare/
come separatore di directory. Pertanto, per ragioni di compatibilità, gli sviluppatori possono utilizzare/
come separatori di directory su tutti i sistemi, ma tenere presente che i valori restituiti dalle funzioni (ad es.realpath
) possono contenere barre retroverse.
- Mentre il
Eliminazione di file e directory
Eliminazione di file
La funzione di unlink
cancella un singolo file e restituisce se l'operazione ha avuto successo.
$filename = '/path/to/file.txt';
if (file_exists($filename)) {
$success = unlink($filename);
if (!$success) {
throw new Exception("Cannot delete $filename");
}
}
Eliminazione di directory, con eliminazione ricorsiva
D'altra parte, le directory dovrebbero essere cancellate con rmdir
. Tuttavia, questa funzione elimina solo le directory vuote. Per eliminare una directory con file, eliminare prima i file nelle directory. Se la directory contiene sottodirectory, potrebbe essere necessaria la ricorsione .
L'esempio seguente esegue la scansione dei file in una directory, cancella i file / directory dei membri in modo ricorsivo e restituisce il numero di file (non di directory) cancellati.
function recurse_delete_dir(string $dir) : int {
$count = 0;
// ensure that $dir ends with a slash so that we can concatenate it with the filenames directly
$dir = rtrim($dir, "/\\") . "/";
// use dir() to list files
$list = dir($dir);
// store the next file name to $file. if $file is false, that's all -- end the loop.
while(($file = $list->read()) !== false) {
if($file === "." || $file === "..") continue;
if(is_file($dir . $file)) {
unlink($dir . $file);
$count++;
} elseif(is_dir($dir . $file)) {
$count += recurse_delete_dir($dir . $file);
}
}
// finally, safe to delete directory!
rmdir($dir);
return $count;
}
Funzioni di convenienza
IO diretto raw
file_get_contents
e file_put_contents
forniscono la possibilità di leggere / scrivere da / su un file da / a una stringa PHP in una singola chiamata.
file_put_contents
può anche essere utilizzato con il flag di FILE_APPEND
da aggiungere a, anziché troncare e sovrascrivere il file. Può essere usato insieme alla LOCK_EX
bit LOCK_EX
per acquisire un blocco esclusivo per il file mentre si procede alla scrittura. I flag di bitmask possono essere uniti con |
Operatore OR bit a bit.
$path = "file.txt";
// reads contents in file.txt to $contents
$contents = file_get_contents($path);
// let's change something... for example, convert the CRLF to LF!
$contents = str_replace("\r\n", "\n", $contents);
// now write it back to file.txt, replacing the original contents
file_put_contents($path, $contents);
FILE_APPEND
è utile per aggiungere file di registro mentre LOCK_EX
aiuta a prevenire le condizioni di competizione della scrittura di file da più processi. Ad esempio, per scrivere in un file di registro relativo alla sessione corrente:
file_put_contents("logins.log", "{$_SESSION["username"]} logged in", FILE_APPEND | LOCK_EX);
CSV IO
fgetcsv($file, $length, $separator)
fgetcsv
analizza la riga dal controllo di file aperti per i campi csv. Restituisce i campi CSV in una matrice in caso di successo o FALSE
in caso di errore.
Per impostazione predefinita, leggerà solo una riga del file CSV.
$file = fopen("contacts.csv","r");
print_r(fgetcsv($file));
print_r(fgetcsv($file,5," "));
fclose($file);
contacts.csv
Kai Jim, Refsnes, Stavanger, Norway
Hege, Refsnes, Stavanger, Norway
Produzione:
Array
(
[0] => Kai Jim
[1] => Refsnes
[2] => Stavanger
[3] => Norway
)
Array
(
[0] => Hege,
)
Lettura diretta di un file su stdout
readfile
copia un file nel buffer di output. readfile () non presenterà alcun problema di memoria, nemmeno durante l'invio di file di grandi dimensioni, da solo.
$file = 'monkey.gif';
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($file).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
readfile($file);
exit;
}
O da un puntatore di file
In alternativa, per cercare un punto nel file per iniziare a copiare su stdout, usa invece fpassthru
. Nell'esempio seguente, gli ultimi 1024 byte vengono copiati su stdout:
$fh = fopen("file.txt", "rb");
fseek($fh, -1024, SEEK_END);
fpassthru($fh);
Lettura di un file in un array
file
restituisce le righe nel file passato in un array. Ogni elemento dell'array corrisponde a una linea nel file, con il newline ancora collegato.
print_r(file("test.txt"));
test.txt
Welcome to File handling
This is to test file handling
Produzione:
Array
(
[0] => Welcome to File handling
[1] => This is to test file handling
)
Ottenere informazioni sui file
Controlla se un percorso è una directory o un file
La funzione is_dir
restituisce se l'argomento è una directory, mentre is_file
restituisce se l'argomento è un file. Usa file_exists
per verificare se lo è.
$dir = "/this/is/a/directory";
$file = "/this/is/a/file.txt";
echo is_dir($dir) ? "$dir is a directory" : "$dir is not a directory", PHP_EOL,
is_file($dir) ? "$dir is a file" : "$dir is not a file", PHP_EOL,
file_exists($dir) ? "$dir exists" : "$dir doesn't exist", PHP_EOL,
is_dir($file) ? "$file is a directory" : "$file is not a directory", PHP_EOL,
is_file($file) ? "$file is a file" : "$file is not a file", PHP_EOL,
file_exists($file) ? "$file exists" : "$file doesn't exist", PHP_EOL;
Questo da:
/this/is/a/directory is a directory
/this/is/a/directory is not a file
/this/is/a/directory exists
/this/is/a/file.txt is not a directory
/this/is/a/file.txt is a file
/this/is/a/file.txt exists
Controllo del tipo di file
Usa filetype
per verificare il tipo di file, che può essere:
-
fifo
-
char
-
dir
-
block
-
link
-
file
-
socket
-
unknown
Passando direttamente il nome del file al tipo di filetype
:
echo filetype("~"); // dir
Si noti che filetype
restituisce false e attiva E_WARNING
se il file non esiste.
Controllo della leggibilità e della scrittura
Passando il nome file alle funzioni is_writable
e is_readable
, verificare se il file è scrivibile o leggibile rispettivamente.
Le funzioni restituiscono false
garbo se il file non esiste.
Controllo dell'accesso ai file / modifica del tempo
L'utilizzo di filemtime
e fileatime
restituisce il timestamp dell'ultima modifica o accesso del file. Il valore di ritorno è un timestamp Unix - vedi Lavorare con date e orari per i dettagli.
echo "File was last modified on " . date("Y-m-d", filemtime("file.txt"));
echo "File was last accessed on " . date("Y-m-d", fileatime("file.txt"));
Ottieni parti del percorso con fileinfo
$fileToAnalyze = ('/var/www/image.png');
$filePathParts = pathinfo($fileToAnalyze);
echo '<pre>';
print_r($filePathParts);
echo '</pre>';
Questo esempio produrrà:
Array
(
[dirname] => /var/www
[basename] => image.png
[extension] => png
[filename] => image
)
Che può essere usato come:
$filePathParts['dirname']
$filePathParts['basename']
$filePathParts['extension']
$filePathParts['filename']
Parametro | Dettagli |
---|---|
$ path | Il percorso completo del file da analizzare |
$ opzione | Una delle quattro opzioni disponibili [PATHINFO_DIRNAME, PATHINFO_BASENAME, PATHINFO_EXTENSION o PATHINFO_FILENAME] |
- Se non viene passata un'opzione (il secondo parametro), viene restituito un array associativo, altrimenti viene restituita una stringa.
- Non convalida che il file esiste.
- Semplicemente analizza la stringa in parti. Nessuna convalida sul file (nessun controllo di tipo mime, ecc.)
- L'estensione è semplicemente l'ultima estensione di
$path
Il percorso per il fileimage.jpg.png
sarebbe.png
anche se tecnicamente un file.jpg
. Un file senza un'estensione non restituirà un elemento di estensione nell'array.
Riduci al minimo l'utilizzo della memoria quando lavori con file di grandi dimensioni
Se abbiamo bisogno di analizzare un file di grandi dimensioni, ad esempio un CSV più di 10 Mbyte contenente milioni di righe, alcuni usano file
funzioni file
o file_get_contents
e finiscono col colpire memory_limit
impostazione memory_limit
con
Dimensione di memoria consentita di byte XXXXX esauriti
errore. Considera la seguente fonte (top-1m.csv ha esattamente 1 milione di righe e ha una dimensione di circa 22 Mbyte)
var_dump(memory_get_usage(true));
$arr = file('top-1m.csv');
var_dump(memory_get_usage(true));
Questo produce:
int(262144)
int(210501632)
perché l'interprete doveva contenere tutte le righe nell'array $arr
, quindi consumava ~ 200 Mbyte di RAM. Nota che non abbiamo ancora fatto nulla con il contenuto dell'array.
Ora considera il seguente codice:
var_dump(memory_get_usage(true));
$index = 1;
if (($handle = fopen("top-1m.csv", "r")) !== FALSE) {
while (($row = fgetcsv($handle, 1000, ",")) !== FALSE) {
file_put_contents('top-1m-reversed.csv',$index . ',' . strrev($row[1]) . PHP_EOL, FILE_APPEND);
$index++;
}
fclose($handle);
}
var_dump(memory_get_usage(true));
quali uscite
int(262144)
int(262144)
quindi non usiamo un singolo byte di memoria in più, ma analizziamo l'intero CSV e lo salviamo su un altro file invertendo il valore della seconda colonna. Questo perché fgetcsv
legge solo una riga e $row
viene sovrascritta in ogni ciclo.
File IO basato su streaming
Aprire un flusso
fopen
apre un handle di file stream, che può essere utilizzato con varie funzioni per la lettura, scrittura, ricerca e altre funzioni su di esso. Questo valore è di tipo di resource
e non può essere passato ad altri thread mantenendo la sua funzionalità.
$f = fopen("errors.log", "a"); // Will try to open errors.log for writing
Il secondo parametro è la modalità del flusso di file:
Modalità | Descrizione |
---|---|
r | Apri in modalità di sola lettura, iniziando dall'inizio del file |
r+ | Aperto per leggere e scrivere, a partire dall'inizio del file |
w | aperto solo per scrittura, a partire dall'inizio del file. Se il file esiste, svuoterà il file. Se non esiste cercherà di crearlo. |
w+ | aperto per leggere e scrivere, a partire dall'inizio del file. Se il file esiste, svuoterà il file. Se non esiste cercherà di crearlo. |
a | apri un file solo per scrittura, a partire dalla fine del file. Se il file non esiste, proverà a crearlo |
a+ | apri un file per leggere e scrivere, iniziando alla fine del file. Se il file non esiste, proverà a crearlo |
x | crea e apri un file solo per scrittura. Se il file esiste, la chiamata fopen fallirà |
x+ | crea e apri un file per leggere e scrivere. Se il file esiste, la chiamata fopen fallirà |
c | apri il file solo per scrittura. Se il file non esiste, proverà a crearlo. Comincerà a scrivere all'inizio del file, ma non svuoterà il file prima della scrittura |
c+ | apri il file per leggere e scrivere. Se il file non esiste, proverà a crearlo. Comincerà a scrivere all'inizio del file, ma non svuoterà il file prima della scrittura |
L'aggiunta di una t
alla modalità (es. A a+b
, wt
, ecc.) In Windows tradurrà "\n"
terminazioni di riga in "\r\n"
quando si lavora con il file. Aggiungi b
dietro la modalità se questo non è previsto, specialmente se si tratta di un file binario.
L'applicazione PHP deve chiudere gli stream utilizzando fclose
quando non vengono più utilizzati per impedire l'errore Too many open files
. Ciò è particolarmente importante nei programmi CLI, dal momento che gli stream vengono chiusi solo quando il runtime si arresta, questo significa che nei web server potrebbe non essere necessario (ma dovrebbe comunque, come pratica per prevenire perdite di risorse) chiudere i flussi se non si prevede che il processo venga eseguito per un lungo periodo e non si apriranno più flussi.
Lettura
L'uso di fread
leggerà il numero dato di byte dal puntatore del file o fino a quando non viene raggiunto un EOF.
Linee di lettura
L'uso di fgets
leggerà il file fino a quando non viene raggiunto un EOL o viene letta la lunghezza specificata.
Sia fread
che fgets
spostano il puntatore del file durante la lettura.
Leggendo tutto ciò che rimane
Usando stream_get_contents
tutti i byte restanti nello stream vengono stream_get_contents
in una stringa e restituiti.
Regolazione della posizione del puntatore del file
Inizialmente dopo aver aperto lo stream, il puntatore del file si trova all'inizio del file (o alla fine, se si utilizza la modalità a
). L'uso della funzione fseek
sposta il puntatore del file in una nuova posizione, relativa a uno dei tre valori:
-
SEEK_SET
: questo è il valore predefinito; l'offset della posizione del file sarà relativo all'inizio del file. -
SEEK_CUR
: lo spostamento della posizione del file sarà relativo alla posizione corrente. -
SEEK_END
: l'offset della posizione del file sarà relativo alla fine del file. Passare un offset negativo è l'uso più comune di questo valore; sposterà la posizione del file sul numero specificato di byte prima della fine del file.
rewind
è una comoda scorciatoia di fseek($fh, 0, SEEK_SET)
.
Utilizzando ftell
mostrerà la posizione assoluta del puntatore del file.
Ad esempio, il seguente script legge salta i primi 10 byte, legge i 10 byte successivi, salta 10 byte, legge i 10 byte successivi e quindi gli ultimi 10 byte in file.txt:
$fh = fopen("file.txt", "rb");
fseek($fh, 10); // start at offset 10
echo fread($fh, 10); // reads 10 bytes
fseek($fh, 10, SEEK_CUR); // skip 10 bytes
echo fread($fh, 10); // read 10 bytes
fseek($fh, -10, SEEK_END); // skip to 10 bytes before EOF
echo fread($fh, 10); // read 10 bytes
fclose($fh);
scrittura
L'utilizzo di fwrite
scrive la stringa fornita nel file partendo dal puntatore del file corrente.
fwrite($fh, "Some text here\n");
Spostamento e copia di file e directory
Copia di file
copy
copia il file sorgente nel primo argomento nella destinazione nel secondo argomento. La destinazione risolta deve trovarsi in una directory già creata.
if (copy('test.txt', 'dest.txt')) {
echo 'File has been copied successfully';
} else {
echo 'Failed to copy file to destination given.'
}
Copia di directory, con ricorsione
Copiare le directory è molto simile all'eliminazione delle directory, ad eccezione del fatto che per la copy
file invece di usare lo unlink
, mentre per le directory si utilizza mkdir
invece di rmdir
, all'inizio invece di trovarsi alla fine della funzione.
function recurse_delete_dir(string $src, string $dest) : int {
$count = 0;
// ensure that $src and $dest end with a slash so that we can concatenate it with the filenames directly
$src = rtrim($dest, "/\\") . "/";
$dest = rtrim($dest, "/\\") . "/";
// use dir() to list files
$list = dir($src);
// create $dest if it does not already exist
@mkdir($dest);
// store the next file name to $file. if $file is false, that's all -- end the loop.
while(($file = $list->read()) !== false) {
if($file === "." || $file === "..") continue;
if(is_file($src . $file)) {
copy($src . $file, $dest . $file);
$count++;
} elseif(is_dir($src . $file)) {
$count += recurse_copy_dir($src . $file, $dest . $file);
}
}
return $count;
}
Rinominare / Moving
Rinominare / spostare file e directory è molto più semplice. Intere directory possono essere spostate o rinominate in una singola chiamata, usando la funzione di rename
.
rename("~/file.txt", "~/file.html");
rename("~/dir", "~/old_dir");
rename("~/dir/file.txt", "~/dir2/file.txt");