PHP
Dateibehandlung
Suche…
Syntax
- int readfile (Zeichenfolge $ filename [, bool $ use_include_path = false [, Ressource $ context]])
Parameter
Parameter | Beschreibung |
---|---|
Dateiname | Der zu lesende Dateiname |
use_include_path | Sie können den optionalen zweiten Parameter verwenden und auf TRUE setzen, wenn Sie auch im include_path nach der Datei suchen möchten. |
Kontext | Eine Kontextstream-Ressource |
Bemerkungen
Dateiname-Syntax
Die meisten Dateinamen, die an Funktionen in diesem Thema übergeben werden, sind:
- Zeichenketten in der Natur.
- Dateinamen können direkt übergeben werden. Wenn Werte anderer Typen übergeben werden, werden sie in String umgewandelt. Dies ist besonders nützlich bei
SplFileInfo
, dem Wert in der Iteration vonDirectoryIterator
.
- Dateinamen können direkt übergeben werden. Wenn Werte anderer Typen übergeben werden, werden sie in String umgewandelt. Dies ist besonders nützlich bei
- Relativ oder absolut
- Sie können absolut sein. Auf Unix-ähnlichen Systemen beginnen absolute Pfade mit
/
, z. B./home/user/file.txt
, während unter Windows absolute Pfade mit dem Laufwerk beginnen, z. B.C:/Users/user/file.txt
- Sie können auch relativ sein, was vom Wert von
getcwd
abhängig ist und vonchdir
geändert werden kann.
- Sie können absolut sein. Auf Unix-ähnlichen Systemen beginnen absolute Pfade mit
- Protokolle akzeptieren.
- Sie können mit
scheme://
, um den Protokoll-Wrapper anzugeben, mit dem verwaltet werden soll. Beispielsweisefile_get_contents("http://example.com")
Inhalte von http://example.com ab .
- Sie können mit
- Slash-kompatibel.
- Während der
DIRECTORY_SEPARATOR
unter Windows ein umgekehrter Schrägstrich ist und das System standardmäßig umgekehrte Schrägstriche für Pfade zurückgibt, kann der Entwickler/
als Verzeichnistrennzeichen verwenden. Aus Kompatibilitätsgründen können Entwickler/
als Verzeichnistrennzeichen auf allen Systemen verwenden.realpath
jedoch, dass die von den Funktionen (z. B.realpath
) zurückgegebenen Werte möglicherweise Backslashes enthalten.
- Während der
Dateien und Verzeichnisse löschen
Dateien löschen
Die unlink
Funktion löscht eine einzelne Datei und gibt zurück, ob die Operation erfolgreich war.
$filename = '/path/to/file.txt';
if (file_exists($filename)) {
$success = unlink($filename);
if (!$success) {
throw new Exception("Cannot delete $filename");
}
}
Löschen von Verzeichnissen mit rekursiver Löschung
Zum anderen sollten Verzeichnisse mit rmdir
gelöscht werden. Diese Funktion löscht jedoch nur leere Verzeichnisse. Um ein Verzeichnis mit Dateien zu löschen, löschen Sie zuerst die Dateien in den Verzeichnissen. Wenn das Verzeichnis Unterverzeichnisse enthält, ist möglicherweise eine Rekursion erforderlich.
Das folgende Beispiel durchsucht Dateien in einem Verzeichnis, löscht Mitgliedsdateien / Verzeichnisse rekursiv und gibt die Anzahl der gelöschten Dateien (nicht Verzeichnisse) zurück.
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;
}
Komfortfunktionen
Rohes direktes IO
file_get_contents
und file_put_contents
bieten die Möglichkeit, in einem einzigen Aufruf von / in eine Datei in / aus einem PHP-String zu schreiben.
file_put_contents
kann auch mit dem Bitmaske-Flag file_put_contents
verwendet werden, um an die FILE_APPEND
anzuhängen, anstatt sie FILE_APPEND
und zu überschreiben. Sie kann zusammen mit der LOCK_EX
Bitmaske verwendet werden, um beim Schreiben eine exklusive Sperre für die Datei zu erhalten. Bitmaskenflags können mit der |
bitweises ODER-Operator.
$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
ist praktisch zum Anhängen an Protokolldateien, während LOCK_EX
beiträgt, die Race-Bedingung beim Schreiben von Dateien aus mehreren Prozessen zu verhindern. So schreiben Sie beispielsweise eine Protokolldatei über die aktuelle Sitzung:
file_put_contents("logins.log", "{$_SESSION["username"]} logged in", FILE_APPEND | LOCK_EX);
CSV IO
fgetcsv($file, $length, $separator)
Die Datei fgetcsv
analysiert die Zeile der geöffneten Datei und prüft, fgetcsv
Felder vorhanden sind. Bei Erfolg wird ein CSV-Feld in einem Array oder bei einem Fehler FALSE
.
Standardmäßig liest es nur eine Zeile der CSV-Datei.
$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
Ausgabe:
Array
(
[0] => Kai Jim
[1] => Refsnes
[2] => Stavanger
[3] => Norway
)
Array
(
[0] => Hege,
)
Eine Datei direkt in stdout einlesen
readfile
kopiert eine Datei in den Ausgabepuffer. Bei readfile () treten selbst beim Senden großer Dateien keine Speicherprobleme auf.
$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;
}
Oder von einem Dateizeiger
fpassthru
einen Punkt in der Datei zu suchen, um mit dem Kopieren nach stdout zu beginnen, verwenden fpassthru
stattdessen fpassthru
. Im folgenden Beispiel werden die letzten 1024 Bytes nach stdout kopiert:
$fh = fopen("file.txt", "rb");
fseek($fh, -1024, SEEK_END);
fpassthru($fh);
Eine Datei in ein Array einlesen
file
gibt die Zeilen in der übergebenen Datei in einem Array zurück. Jedes Element des Arrays entspricht einer Zeile in der Datei, wobei der Zeilenumbruch noch angefügt ist.
print_r(file("test.txt"));
test.txt
Welcome to File handling
This is to test file handling
Ausgabe:
Array
(
[0] => Welcome to File handling
[1] => This is to test file handling
)
Dateiinformationen abrufen
Prüfen Sie, ob ein Pfad ein Verzeichnis oder eine Datei ist
Die Funktion is_dir
zurück, ob das Argument ein Verzeichnis ist, während is_file
zurückgibt, ob das Argument eine Datei ist. Verwenden Sie file_exists
, um zu überprüfen, ob dies der file_exists
ist.
$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;
Das gibt:
/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
Dateityp überprüfen
Verwenden Sie den filetype
, um den filetype
zu überprüfen. filetype
sein:
-
fifo
-
char
-
dir
-
block
-
link
-
file
-
socket
-
unknown
Den Dateinamen direkt an den filetype
:
echo filetype("~"); // dir
Beachten Sie, dass der filetype
false zurückgibt und ein E_WARNING
auslöst, wenn die Datei nicht vorhanden ist.
Lesbarkeit und Beschreibbarkeit prüfen
Wenn Sie den Dateinamen an die Funktionen is_writable
und is_readable
, überprüfen Sie, ob die Datei schreibbar oder lesbar ist.
Die Funktionen geben ordnungsgemäß false
wenn die Datei nicht vorhanden ist.
Dateizugriffs- / Änderungszeit prüfen
Die Verwendung von filemtime
und fileatime
gibt den Zeitstempel der letzten Änderung oder des Zugriffs auf die Datei zurück. Der Rückgabewert ist ein Unix-Zeitstempel - Einzelheiten finden Sie unter Arbeiten mit Datum und Uhrzeit .
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"));
Erhalte Pfadteile mit fileinfo
$fileToAnalyze = ('/var/www/image.png');
$filePathParts = pathinfo($fileToAnalyze);
echo '<pre>';
print_r($filePathParts);
echo '</pre>';
Dieses Beispiel gibt Folgendes aus:
Array
(
[dirname] => /var/www
[basename] => image.png
[extension] => png
[filename] => image
)
Welches kann verwendet werden als:
$filePathParts['dirname']
$filePathParts['basename']
$filePathParts['extension']
$filePathParts['filename']
Parameter | Einzelheiten |
---|---|
$ path | Der vollständige Pfad der zu analysierenden Datei |
Option $ | Eine von vier verfügbaren Optionen [PATHINFO_DIRNAME, PATHINFO_BASENAME, PATHINFO_EXTENSION oder PATHINFO_FILENAME] |
- Wenn eine Option (der zweite Parameter) nicht übergeben wird, wird ein assoziatives Array zurückgegeben, andernfalls wird ein String zurückgegeben.
- Überprüft nicht, dass die Datei vorhanden ist.
- Parst die Saite einfach in Teile. Die Datei wird nicht validiert (keine Überprüfung des Mime-Typs usw.).
- Die Erweiterung ist einfach die letzte Erweiterung von
$path
Der Pfad für die Dateiimage.jpg.png
wäre.png
auch wenn es sich technisch um eine.jpg
Datei handelt. Eine Datei ohne Erweiterung gibt kein Erweiterungselement im Array zurück.
Minimieren Sie den Speicherverbrauch beim Umgang mit großen Dateien
Wenn eine große Datei analysiert werden muss, z. B. eine CSV mit mehr als 10 MByte, die Millionen von Zeilen enthält, verwenden einige die Funktionen file
oder file_get_contents
und enden mit der Einstellung memory_limit
mit
Zulässige Speichergröße von XXXXX Byte erschöpft
Error. Betrachten Sie die folgende Quelle (top-1m.csv hat genau 1 Million Zeilen und ist ungefähr 22 MB groß)
var_dump(memory_get_usage(true));
$arr = file('top-1m.csv');
var_dump(memory_get_usage(true));
Dies gibt aus:
int(262144)
int(210501632)
Da der Interpreter alle Zeilen im Array $arr
, verbrauchte er ~ 200 MB RAM. Beachten Sie, dass wir mit dem Inhalt des Arrays noch nichts unternommen haben.
Betrachten Sie nun den folgenden Code:
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));
welche Ausgänge
int(262144)
int(262144)
Wir verwenden also kein einzelnes zusätzliches Byte Speicher, sondern analysieren die gesamte CSV-Datei und speichern sie in einer anderen Datei, wobei der Wert der 2. Spalte umgekehrt wird. Das liegt daran, dass fgetcsv
nur eine Zeile liest und $row
in jeder Schleife überschrieben wird.
Stream-basierte Datei-IO
Einen Stream öffnen
fopen
öffnet ein Dateistream-Handle, das mit verschiedenen Funktionen zum Lesen, Schreiben, Suchen und anderen Funktionen darüber verwendet werden kann. Dieser Wert ist vom resource
und kann nicht an andere Threads übergeben werden, die ihre Funktionalität beibehalten.
$f = fopen("errors.log", "a"); // Will try to open errors.log for writing
Der zweite Parameter ist der Modus des Dateistreams:
Modus | Beschreibung |
---|---|
r | Öffnet den schreibgeschützten Modus und beginnt am Anfang der Datei |
r+ | Zum Lesen und Schreiben öffnen, beginnend am Anfang der Datei |
w | Nur zum Schreiben geöffnet, beginnend am Anfang der Datei. Wenn die Datei vorhanden ist, wird die Datei geleert. Wenn es nicht existiert, wird es versuchen, es zu erstellen. |
w+ | Zum Lesen und Schreiben geöffnet, beginnend am Anfang der Datei. Wenn die Datei vorhanden ist, wird die Datei geleert. Wenn es nicht existiert, wird es versuchen, es zu erstellen. |
a | Öffnen Sie eine Datei nur zum Schreiben, beginnend am Ende der Datei. Wenn die Datei nicht vorhanden ist, wird versucht, sie zu erstellen |
a+ | Öffnen Sie eine Datei zum Lesen und Schreiben, und zwar am Ende der Datei. Wenn die Datei nicht vorhanden ist, wird versucht, sie zu erstellen |
x | Erstellen und öffnen Sie eine Datei nur zum Schreiben. Wenn die Datei vorhanden ist, fopen der fopen Aufruf fehl |
x+ | Erstellen und öffnen Sie eine Datei zum Lesen und Schreiben. Wenn die Datei vorhanden ist, fopen der fopen Aufruf fehl |
c | Öffnen Sie die Datei nur zum Schreiben. Wenn die Datei nicht vorhanden ist, wird versucht, sie zu erstellen. Das Schreiben beginnt am Anfang der Datei, leert die Datei jedoch nicht vor dem Schreiben |
c+ | Öffnen Sie die Datei zum Lesen und Schreiben. Wenn die Datei nicht vorhanden ist, wird versucht, sie zu erstellen. Das Schreiben beginnt am Anfang der Datei, leert die Datei jedoch nicht vor dem Schreiben |
Wenn Sie in Windows ein t
hinter dem Modus hinzufügen (z. B. a+b
, wt
usw.), werden "\n"
Zeilenenden in "\r\n"
wenn Sie mit der Datei arbeiten. Fügen Sie b
hinter dem Modus ein, wenn dies nicht beabsichtigt ist, insbesondere wenn es sich um eine Binärdatei handelt.
Die PHP-Anwendung sollte Streams mit fclose
wenn sie nicht mehr verwendet werden, um den Fehler Too many open files
zu verhindern. Dies ist besonders wichtig in CLI - Programmen, da die Ströme nur dann geschlossen , wenn die Laufzeit ausschaltet - dies bedeutet , dass in Web - Servern, ist es nicht notwendig sein kann (aber immer noch sollte, als eine Praxis Ressource - Leck zu verhindern) , die Ströme zu schließen Wenn Sie nicht davon ausgehen, dass der Prozess längere Zeit ausgeführt wird, und viele Streams nicht geöffnet werden.
lesen
Mit fread
wird die angegebene Anzahl von Bytes aus dem Dateizeiger gelesen oder bis ein EOF erreicht wird.
Zeilen lesen
Mit fgets
wird die Datei gelesen, bis eine EOL erreicht wird oder die angegebene Länge gelesen wird.
fread
und fgets
bewegen den Dateizeiger während des Lesens.
Lesen Sie alles, was noch übrig ist
Bei Verwendung von stream_get_contents
werden alle verbleibenden Bytes im Stream in einen String umgewandelt und zurückgegeben.
Dateizeigerposition anpassen
Nach dem Öffnen des Streams befindet sich der Dateizeiger am Anfang der Datei (oder am Ende, wenn der Modus a
verwendet wird). Mit der Funktion fseek
wird der Dateizeiger relativ zu einem der drei Werte an eine neue Position fseek
:
-
SEEK_SET
: Dies ist der Standardwert. Der Versatz der Dateiposition ist relativ zum Dateianfang. -
SEEK_CUR
: Der Versatz derSEEK_CUR
ist relativ zur aktuellen Position. -
SEEK_END
: Der Versatz derSEEK_END
ist relativ zum Ende der Datei. Das Übergeben eines negativen Offsets wird für diesen Wert am häufigsten verwendet. Die Dateiposition wird vor dem Ende der Datei auf die angegebene Anzahl von Bytes verschoben.
rewind
ist eine praktische Abkürzung von fseek($fh, 0, SEEK_SET)
.
Bei Verwendung von ftell
wird die absolute Position des Dateizeigers ftell
.
Das folgende Skript liest beispielsweise die ersten 10 Bytes, liest die nächsten 10 Bytes, überspringt 10 Bytes, liest die nächsten 10 Bytes und dann die letzten 10 Bytes 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);
Schreiben
Bei Verwendung von fwrite
der bereitgestellte String ab dem aktuellen Dateizeiger in die Datei geschrieben.
fwrite($fh, "Some text here\n");
Dateien und Verzeichnisse verschieben und kopieren
Dateien kopieren
copy
kopiert die Quelldatei im ersten Argument an das Ziel im zweiten Argument. Das aufgelöste Ziel muss sich in einem Verzeichnis befinden, das bereits erstellt wurde.
if (copy('test.txt', 'dest.txt')) {
echo 'File has been copied successfully';
} else {
echo 'Failed to copy file to destination given.'
}
Verzeichnisse kopieren mit Rekursion
Das Kopieren von Verzeichnissen ist dem Löschen von Verzeichnissen sehr ähnlich, mit der Ausnahme, dass für Dateien copy
anstelle von unlink
verwendet wird, während für Verzeichnisse mkdir
anstelle von rmdir
verwendet wird, anstatt am Ende der Funktion.
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;
}
Umbenennen / Verschieben
Das Umbenennen / Verschieben von Dateien und Verzeichnissen ist wesentlich einfacher. Ganze Verzeichnisse können in einem einzigen Aufruf verschoben oder umbenannt werden, die mit rename
rename("~/file.txt", "~/file.html");
rename("~/dir", "~/old_dir");
rename("~/dir/file.txt", "~/dir2/file.txt");