Lekce 2 - Práce s textovými soubory v PHP
V předchozí lekci, Úvod do práce se soubory v PHP, jsme si ujasnili, jaké typy souborů existují a jak pracovat s cestami k těmto souborům. V této lekci se podíváme také na to, jak pracovat s nestrukturovaným prostým textem v jazyce PHP.
Přestože se v této lekci budeme zaměřovat primárně na práci s nestrukturovanými textovými soubory, tak funkce, které si zde ukážeme, budeme využívat i v dalších lekcích při práci se strukturovanými soubory.
Způsoby čtení a zápisu souborů v PHP
V PHP lze číst a zapisovat soubory dvěma způsoby:
- pomocí jednoúčelových funkcí a
- pomocí tzv. resources.
První způsob má výhodu ve své jednoduchosti a rychlosti. PHP má funkce, které při svém zavolání přečtou či zapíšou celý obsah souboru. Kdybychom ale například chtěli pracovat po částech s velkými soubory nebo přímo při čtení/zápisu pracovat se souborem CSV, je tato abstrakce na škodu. V takovém případě využíváme tzv. resources. S druhým způsobem se však seznámíme až v další lekci.
Práce se soubory pomocí jednoúčelových funkcí
Nyní se seznámíme s jednoúčelovými funkcemi.
file_put_contents()
– zápis řetězce do souboru
Předtím, než budeme soubor číst, si ukážeme, jak takový soubor
vytvořit a jak do něj zapsat nějaký text. K zápisu řetězce
(string
) do souboru slouží v PHP funkce
file_put_contents()
. Jako první argument přijímá cestu k
zapisovanému souboru a jako druhý argument onen textový řetězec, který
chceme zapsat. Jestliže cílový soubor neexistuje, pokusí se ho PHP
vytvořit:
$soubor = "muj_text.txt"; $text = "Ahoj!<br />\nToto je text, který se objeví v našem souboru :-)"; file_put_contents($soubor, $text);
Obsah souboru muj_text.txt
by po spuštění skriptu měl být
takovýto:
Ahoj!<br /> Toto je text, který se objeví v našem souboru :-)
Víme tedy, že sekvence \n
udělala v textovém souboru nový
řádek, stejně jako tag <br />
vytvoří nový řádek v
prohlížeči.
Ošetření chyb
Během vykonávání programu může dojít k chybám a u práce se soubory
tomu není jinak. Funkce file_put_contents()
vrací počet bajtů,
které zapsala, ale když dojde k chybě, vrací booleovskou hodnotu
false
. V příkladu výše by měl kód pro zápis do souboru
vypadat správně takto:
$zapsano = file_put_contents($soubor, $text); if ($zapsano === FALSE) { echo("Při zápisu do souboru nastala chyba!"); } else { echo("Zápis do souboru se povedl!<br />Počet zapsaných bajtů: "), $zapsano; }
V prohlížeči by se nám mělo ukázat toto:
V případě chyby zase toto:
Můžeme si všimnout, že na porovnávání návratové hodnoty a
booleovské hodnoty false
používáme operátor ===
,
neboli tzv. strict comparison operator. Ten určuje, že
porovnávané hodnoty musí být nejen "stejné", ale musí být i
stejného datového typu. To je důležité, protože funkce
file_put_contents()
by mohla "zapsat" i 0 bajtů,
což nemusí nutně značit chybový stav. V případě použití operátoru
==
(tzv. loose comparison operator), který asi
už dobře známe, by PHP jakožto slabě typovaný jazyk
vyhodnocovalo, že 0
je false
. A těžko nalezitelná
chyba v programu by byla na světě
Chyba zápisu kvůli nedostatečných oprávnění
Pokud si skript spustíme na vlastním serveru a skončí s chybou,
pravděpodobně skript nemá právo do souboru zapisovat. Jestliže soubor již
existuje, musíme uživatelskému účtu, pod kterým PHP běží, přidělit k
souboru oprávnění pro zápis. Pokud soubor ještě
neexistuje, musí uživatel dostat práva k zápisu do složky, ve které se
bude soubor vytvářet. Pokud náš server používá operační systém Linux,
problematika oprávnění je probírána v lekci Linuxový
terminál (Bash) - Oprávnění, instalace a procesy v kurzu Základy Linuxu
Připisování obsahu do souboru, tzv. append režim
Jestliže už soubor existuje a je v něm nějaký obsah, funkce
file_put_contents()
ho standardně vymaže a
vytvoří soubor nový. Kdybychom tvořili například
návštěvní knihu, bylo by toto chování nežádoucí. Funkce ale nabízí
tzv. append režim, kdy platí, že se nový obsah přidá na
konec toho existujícího. Do tohoto režimu se můžeme dostat tak, že funkci
jako třetí argument předáme konstantu FILE_APPEND
:
$zapsano = file_put_contents($soubor, $text, FILE_APPEND);
Zamykání souborů
Kdybychom měli na webu hodně návštěvníků zároveň a každý zapisoval
něco do souboru, mohlo by se stát, že by zápis do stejného souboru proběhl
vícekrát ve stejnou chvíli a náš soubor by se poškodil.
Tomuto můžeme předejít tím, že funkci předáme jako třetí argument
konstantu LOCK_EX
. Operace zápisu bude takto
atomická (tzn. veškeré zápisy budou probíhat po sobě,
nikoliv najednou):
$zapsano = file_put_contents($soubor, $text, LOCK_EX);
Kdybychom chtěli zkombinovat append režim se zamykáním, obě konstanty
spojíme pomocí bitového operátoru OR
(|
):
$zapsano = file_put_contents($soubor, $text, FILE_APPEND | LOCK_EX);
file_get_contents()
– přečtení souboru do řetězce
Soubor již máme vytvořený, a tak jej můžeme přečíst. Funkce
file_get_contents()
vezme obsah souboru, jehož cestu jí předáme
v prvním argumentu, celý ho přečte a vrátí nám ho jako řetězec. Stačí
ji předat jediný argument, který je název souboru. Vrací buď přečtená
data jako řetězec, nebo false
v případě chyby:
$soubor = "muj_text.txt"; $obsahSouboru = file_get_contents($soubor); if ($obsahSouboru === FALSE) { echo("Při čtení souboru došlo k chybě!"); } else { echo("Soubor byl úspěšně přečten!<br />Obsah souboru:<br />"), $obsahSouboru; }
Výstup skriptu bude vypadat takto:
Vzhledem k tomu, že prázdný řetězec je také standardně brán jako
false
, použijeme i zde na kontrolu chyby operátor
===
.
file()
–
přečtení souboru po řádcích do pole
Funkce file()
pracuje stejně jako
file_get_contents()
s tím rozdílem, že obsah souboru nepřečte
do řetězce, ale rozdělí jej po řádcích a vrátí pole těchto
řádků. Kdybychom například v souboru měli uložené komentáře k
našemu článku a každý měli na samostatném řádku, tato funkce by se nám
hodila více, než file_get_contents()
, protože bychom
pravděpodobně chtěli jednotlivé komentáře před výpisem obalit do
nějakého rámečku apod.:
$soubor = "muj_text.txt"; $radky = file($soubor); if ($radky === FALSE) { echo("Při čtení souboru došlo k chybě!"); } else { foreach ($radky as $i => $radek) { echo "Řádek č. ", ($i + 1), ": ", $radek, "<br />"; } }
Funkci echo()
můžeme volat i bez závorek, v případě výše
se nám to může vyplatit, nemusíme psát hodně závorek.
Výstup:
readfile()
– vypsání souboru přímo do prohlížeče
Může se stát, že obsah souboru nebudeme chtít zpracovávat, ale pouze
vypsat návštěvníkovi našich webových stránek. Výhoda funkce
readfile()
oproti dříve zmiňovaným je ta, že může
pracovat i s velmi velkými soubory. Odpadá zde totiž mezikrok v
podobě zapsání textu do proměnné (= do paměti RAM), která má oproti
diskům omezenou velikost. Kdybychom takto vypisovali například databázi,
která má několik gigabajtů, tak by nám to s dříve zmiňovanými funkcemi
neprošlo, zatímco s funkcí readfile()
ano :
$soubor = "muj_text.txt"; $bytu = readfile($soubor); if ($obsahSouboru === FALSE) { echo("Při vypisování souboru došlo k chybě!"); } else { echo("<br /><br />Soubor byl vypsán!<br />Vypsáno bajtů: "), $bytu; }
Výstup:
Jak vidíme, tak v proměnné $bytu
budeme mít pouze počet
přečtených bajtů, zatímco samotný obsah souboru skončí v prohlížeči
Zdrojové kódy příkladů z této lekce naleznete ke stažení níže.
V následujícím cvičení, Řešené úlohy k 1.-2. lekci práce se soubory v PHP, si procvičíme nabyté zkušenosti z předchozích lekcí.
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 63x (3.06 kB)
Aplikace je včetně zdrojových kódů v jazyce PHP