PHP
Bestandsbehandeling
Zoeken…
Syntaxis
- int readfile (string $ bestandsnaam [, bool $ use_include_path = false [, resource $ context]])
parameters
Parameter | Beschrijving |
---|---|
bestandsnaam | De bestandsnaam wordt gelezen. |
use_include_path | U kunt de optionele tweede parameter gebruiken en deze op TRUE instellen als u ook naar het bestand in het include_path wilt zoeken. |
context | Een contextstroombron. |
Opmerkingen
Syntaxis van de bestandsnaam
De meeste bestandsnamen die worden doorgegeven aan functies in dit onderwerp zijn:
- Strings in de natuur.
- Bestandsnamen kunnen direct worden doorgegeven. Als waarden van andere typen worden doorgegeven, worden deze naar string gegoten. Dit is vooral handig met
SplFileInfo
, de waarde in de iteratie vanDirectoryIterator
.
- Bestandsnamen kunnen direct worden doorgegeven. Als waarden van andere typen worden doorgegeven, worden deze naar string gegoten. Dit is vooral handig met
- Relatief of absoluut.
- Ze kunnen absoluut zijn. Op Unix-achtige systemen beginnen absolute paden met
/
, bijvoorbeeld/home/user/file.txt
, terwijl op Windows absolute paden beginnen met de schijf, bijvoorbeeldC:/Users/user/file.txt
- Ze kunnen ook relatief zijn, wat afhankelijk is van de waarde van
getcwd
en kan worden gewijzigd doorchdir
.
- Ze kunnen absoluut zijn. Op Unix-achtige systemen beginnen absolute paden met
- Accepteer protocollen.
- Ze kunnen beginnen met
scheme://
om de protocolverpakking op te geven waarmee moet worden beheerd. Zofile_get_contents("http://example.com")
inhoud op van http://example.com .
- Ze kunnen beginnen met
- Slash-compatibel.
- Hoewel de
DIRECTORY_SEPARATOR
op Windows een backslash is en het systeem standaard backslashes voor paden retourneert, kan de ontwikkelaar nog steeds/
als mapscheidingsteken. Daarom kunnen ontwikkelaars voor compatibiliteit/
als directory-scheidingstekens op alle systemen gebruiken, maarrealpath
er rekening mee dat de waarden die door de functies worden geretourneerd (bijvoorbeeldrealpath
) backslashes kunnen bevatten.
- Hoewel de
Bestanden en mappen verwijderen
Bestanden verwijderen
De functie voor unlink
verwijdert een enkel bestand en retourneert of de bewerking is geslaagd.
$filename = '/path/to/file.txt';
if (file_exists($filename)) {
$success = unlink($filename);
if (!$success) {
throw new Exception("Cannot delete $filename");
}
}
Mappen verwijderen, met recursieve verwijdering
Aan de andere kant moeten mappen worden verwijderd met rmdir
. Met deze functie worden echter alleen lege mappen verwijderd. Om een map met bestanden te verwijderen, verwijdert u eerst de bestanden in de mappen. Als de map subdirectories bevat, kan recursie nodig zijn.
In het volgende voorbeeld worden bestanden in een map gescand, worden lidbestanden / mappen recursief verwijderd en wordt het aantal verwijderde bestanden (geen mappen) geretourneerd.
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;
}
Gemak functies
Ruwe directe IO
file_get_contents
en file_put_contents
bieden de mogelijkheid om van / naar een bestand naar / van een PHP-string te lezen / schrijven in een enkele aanroep.
file_put_contents
kunnen ook worden gebruikt met de FILE_APPEND
om het bestand toe te voegen in plaats van af te FILE_APPEND
en te overschrijven. Het kan samen met LOCK_EX
worden gebruikt om een exclusieve vergrendeling van het bestand te verkrijgen tijdens het schrijven. Bitmasker vlaggen kunnen worden samengevoegd met de |
bitsgewijze OF-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
is handig om toe te voegen aan logbestanden, terwijl LOCK_EX
voorkomt dat de race van het schrijven van bestanden door meerdere processen wordt belemmerd. Om bijvoorbeeld naar een logbestand over de huidige sessie te schrijven:
file_put_contents("logins.log", "{$_SESSION["username"]} logged in", FILE_APPEND | LOCK_EX);
CSV IO
fgetcsv($file, $length, $separator)
De fgetcsv
parseert regel van open bestandscontrole voor csv-velden. Het retourneert CSV-velden in een array bij succes of FALSE
bij mislukking.
Standaard wordt slechts één regel van het CSV-bestand gelezen.
$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
Output:
Array
(
[0] => Kai Jim
[1] => Refsnes
[2] => Stavanger
[3] => Norway
)
Array
(
[0] => Hege,
)
Een bestand rechtstreeks naar stdout lezen
readfile
kopieert een bestand naar de uitvoerbuffer. readfile () zal op zichzelf geen geheugenproblemen veroorzaken, zelfs niet wanneer grote bestanden worden verzonden.
$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;
}
Of van een bestandsaanwijzer
Als alternatief kunt u in plaats daarvan fpassthru
gebruiken om een punt in het bestand te zoeken om te beginnen met kopiëren naar stdout. In het volgende voorbeeld worden de laatste 1024 bytes gekopieerd naar stdout:
$fh = fopen("file.txt", "rb");
fseek($fh, -1024, SEEK_END);
fpassthru($fh);
Een bestand in een array lezen
file
retourneert de regels in het doorgegeven bestand in een array. Elk element van de array komt overeen met een regel in het bestand, met de nieuwe regel nog steeds gekoppeld.
print_r(file("test.txt"));
test.txt
Welcome to File handling
This is to test file handling
Output:
Array
(
[0] => Welcome to File handling
[1] => This is to test file handling
)
Bestandsinformatie ophalen
Controleer of een pad een map of een bestand is
De functie is_dir
retourneert of het argument een map is, terwijl is_file
retourneert of het argument een bestand is. Gebruik file_exists
om te controleren of dit het geval is.
$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;
Dit geeft:
/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
Bestandstype controleren
Gebruik filetype
om het filetype
te controleren. Dit kan zijn:
-
fifo
-
char
-
dir
-
block
-
link
-
file
-
socket
-
unknown
De filetype
direct aan het filetype
doorgeven:
echo filetype("~"); // dir
Merk op dat het filetype
false retourneert en een E_WARNING
als het bestand niet bestaat.
Controle van de leesbaarheid en schrijfbaarheid
Door de bestandsnaam door te geven aan de functies is_writable
en is_readable
, controleert u of het bestand respectievelijk schrijfbaar of leesbaar is.
De functies retourneren netjes false
als het bestand niet bestaat.
Bestandstoegang controleren / tijd wijzigen
Als u filemtime
en fileatime
wordt de tijdstempel van de laatste wijziging of toegang van het bestand geretourneerd. De retourwaarde is een Unix-tijdstempel - zie Werken met datums en tijd voor meer informatie.
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"));
Download paddelen met fileinfo
$fileToAnalyze = ('/var/www/image.png');
$filePathParts = pathinfo($fileToAnalyze);
echo '<pre>';
print_r($filePathParts);
echo '</pre>';
In dit voorbeeld wordt weergegeven:
Array
(
[dirname] => /var/www
[basename] => image.png
[extension] => png
[filename] => image
)
Die kan worden gebruikt als:
$filePathParts['dirname']
$filePathParts['basename']
$filePathParts['extension']
$filePathParts['filename']
Parameter | Details |
---|---|
$ path | Het volledige pad van het te parseren bestand |
$ optie | Een van de vier beschikbare opties [PATHINFO_DIRNAME, PATHINFO_BASENAME, PATHINFO_EXTENSION of PATHINFO_FILENAME] |
- Als een optie (de tweede parameter) niet wordt doorgegeven, wordt een associatieve array geretourneerd, anders wordt een tekenreeks geretourneerd.
- Bevestigt niet dat het bestand bestaat.
- Ontleedt de string eenvoudig in delen. Er wordt geen validatie uitgevoerd op het bestand (geen mime-type controle, enz.)
- De extensie is gewoon de laatste extensie van
$path
Het pad voor het bestandimage.jpg.png
zou.png
ook al is het technisch een.jpg
bestand. Een bestand zonder extensie retourneert geen extensie-element in de array.
Minimaliseer geheugengebruik bij grote bestanden
Als we een groot bestand moeten parseren, bijvoorbeeld een CSV van meer dan 10 Mbytes met miljoenen rijen, gebruiken file_get_contents
functies file
of file_get_contents
en eindigen met het raken van de memory_limit
instelling met
Toegestane geheugengrootte van XXXXX bytes uitgeput
fout. Overweeg de volgende bron (top-1m.csv heeft exact 1 miljoen rijen en is ongeveer 22 MB groot)
var_dump(memory_get_usage(true));
$arr = file('top-1m.csv');
var_dump(memory_get_usage(true));
Dit geeft uit:
int(262144)
int(210501632)
omdat de tolk alle rijen in $arr
array moest vasthouden, dus hij verbruikt ~ 200 Mbytes RAM. Merk op dat we zelfs niets hebben gedaan met de inhoud van de array.
Overweeg nu de volgende 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));
welke uitgangen
int(262144)
int(262144)
dus we gebruiken geen enkele extra byte geheugen, maar ontleden de hele CSV en slaan deze op in een ander bestand om de waarde van de 2e kolom om te keren. Dat komt omdat fgetcsv
slechts één rij leest en $row
in elke lus wordt overschreven.
Stream-gebaseerd bestand IO
Een stream openen
fopen
opent een file stream-handle, die kan worden gebruikt met verschillende functies voor lezen, schrijven, zoeken en andere functies. Deze waarde is van resource
type resource
en kan niet worden doorgegeven aan andere threads die de functionaliteit ervan behouden.
$f = fopen("errors.log", "a"); // Will try to open errors.log for writing
De tweede parameter is de modus van de bestandsstream:
mode | Beschrijving |
---|---|
r | Openen in alleen-lezen modus, beginnend bij het begin van het bestand |
r+ | Openen voor lezen en schrijven, beginnend bij het begin van het bestand |
w | alleen geopend voor schrijven, beginnend bij het begin van het bestand. Als het bestand bestaat, wordt het bestand leeggemaakt. Als het niet bestaat, probeert het het te maken. |
w+ | open voor lezen en schrijven, beginnend bij het begin van het bestand. Als het bestand bestaat, wordt het bestand leeggemaakt. Als het niet bestaat, probeert het het te maken. |
a | open een bestand om alleen te schrijven, beginnend aan het einde van het bestand. Als het bestand niet bestaat, probeert het het te maken |
a+ | open een bestand voor lezen en schrijven, beginnend aan het einde van het bestand. Als het bestand niet bestaat, probeert het het te maken |
x | maak en open een bestand om alleen te schrijven. Als het bestand bestaat, mislukt de fopen oproep |
x+ | maak en open een bestand voor lezen en schrijven. Als het bestand bestaat, mislukt de fopen oproep |
c | open het bestand alleen voor schrijven. Als het bestand niet bestaat, probeert het het te maken. Het begint met schrijven aan het begin van het bestand, maar zal het bestand niet leegmaken voordat het wordt geschreven |
c+ | open het bestand voor lezen en schrijven. Als het bestand niet bestaat, probeert het het te maken. Het begint met schrijven aan het begin van het bestand, maar zal het bestand niet leegmaken voordat het wordt geschreven |
Als u een t
achter de modus toevoegt (bijvoorbeeld a+b
, wt
, enz.) In Windows, vertaalt u "\n"
regeleinden bij het werken met het bestand naar "\r\n"
. Voeg b
achter de modus toe als dit niet de bedoeling is, vooral als het een binair bestand is.
De PHP-toepassing moet streams sluiten met fclose
wanneer ze niet langer worden gebruikt om de fout Too many open files
te voorkomen. Dit is vooral belangrijk in CLI-programma's, omdat de streams alleen worden gesloten wanneer de runtime wordt afgesloten - dit betekent dat het in webservers misschien niet nodig is (maar toch zou moeten zijn , als een methode om lekken van bronnen te voorkomen) om de streams te sluiten als u niet verwacht dat het proces lang zal duren en niet veel streams zal openen.
Lezing
Als u fread
wordt het gegeven aantal bytes van de bestandspointer gelezen of totdat een EOF is bereikt.
Leesregels
Met behulp van fgets
wordt het bestand gelezen totdat een EOL is bereikt of de opgegeven lengte is gelezen.
Zowel fread
als fgets
verplaatsen de bestandsaanwijzer tijdens het lezen.
Alles lezen dat overblijft
Als je stream_get_contents
worden alle resterende bytes in de stream omgezet in een tekenreeks en wordt deze geretourneerd.
Positie van bestandsaanwijzer aanpassen
Aanvankelijk staat de bestandspointer na het openen van de stream aan het begin van het bestand (of het einde, als de modus a
wordt gebruikt). Met behulp van de fseek
functie wordt de bestandspointer naar een nieuwe positie verplaatst, relatief ten opzichte van een van de drie waarden:
-
SEEK_SET
: dit is de standaardwaarde; de bestandspositie-offset is relatief ten opzichte van het begin van het bestand. -
SEEK_CUR
: de verschuiving van de bestandspositie is relatief ten opzichte van de huidige positie. -
SEEK_END
: de verschuiving van de bestandspositie is relatief ten opzichte van het einde van het bestand. Het passeren van een negatieve offset is het meest voorkomende gebruik voor deze waarde; het verplaatst de bestandspositie naar het opgegeven aantal bytes vóór het einde van het bestand.
rewind
is een handige sneltoets van fseek($fh, 0, SEEK_SET)
.
Met ftell
wordt de absolute positie van de bestandspointer getoond.
Het volgende script leest bijvoorbeeld slaat de eerste 10 bytes over, leest de volgende 10 bytes, slaat 10 bytes over, leest de volgende 10 bytes en vervolgens de laatste 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);
Schrijven
Met behulp van fwrite
de opgegeven tekenreeks naar het bestand geschreven, beginnend bij de huidige bestandsaanwijzer.
fwrite($fh, "Some text here\n");
Bestanden en mappen verplaatsen en kopiëren
Bestanden kopiëren
copy
kopieert het bronbestand in het eerste argument naar de bestemming in het tweede argument. De opgeloste bestemming moet zich in een map bevinden die al is gemaakt.
if (copy('test.txt', 'dest.txt')) {
echo 'File has been copied successfully';
} else {
echo 'Failed to copy file to destination given.'
}
Mappen kopiëren, met recursie
Het kopiëren van mappen is vrijwel hetzelfde als het verwijderen van mappen, behalve dat voor bestanden copy
plaats van unlink
wordt gebruikt, terwijl voor mappen mkdir
plaats van rmdir
wordt gebruikt, aan het begin in plaats van aan het einde van de functie.
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;
}
Hernoemen / verplaatsen
Bestanden en mappen hernoemen / verplaatsen is veel eenvoudiger. Hele mappen kunnen in een enkele oproep worden verplaatst of hernoemd met behulp van de functie rename
.
rename("~/file.txt", "~/file.html");
rename("~/dir", "~/old_dir");
rename("~/dir/file.txt", "~/dir2/file.txt");