Lekce 11: Práce se soubory I
- Práce se soubory patří stále mezi základní věci a proto si ukážeme jak se vytváří a vůbec používají soubory.
- Pokud pracujem s daty, tak je dobré si je někam ukládat. Na to může sloužít i databáze, ale tu zatím neumíme.
Vytváříme soubory
- Práce se soubory je opět celkem široké téma, takže si ukážeme takové základy, co by jsme měli znát.
- Prvním funkcí, co se naučíme bude fopen(). Tato funkce slouží nejenom pro vytvoření souboru.
- U té to funkce si zadáváme mód, pod kterým se má soubor otevřít nebo vytvořit.
- Funkce má 4 parametry, takže si je ukážeme postupně. První parametr je název souboru a druhý slouží právě pro mód.
$soubor = fopen("file.txt", 'w'); // vytvori novy soubor "file.txt" pouze pro zapis - w
-Uvedu zde možné módy, které můžete použít místo "w":
r - slouží pouze pro čtení a soubor čte od začátku do konce
r+ - to samé jako r, jen s tím rozdílem, že do souboru může i zapisovat
w - slouží pouze pro zápis a zapisuje od začátku do konce a pokud soubor neexistuje, tak ho vytvoří
w+ - opět to samé jako u w, jen s rozdílem, že ho může i číst
a - slouží pouze pro zápis a čte soubor od konce a pokud neexistuje, tak ho vytvoří
a+ - to samé jako u a, jen soubor může i číst
x - vytvoří soubor a otevřeho pouze pro čtení a čte soubor od začátku do konce.. ale.. pokud soubor již bude existovat, tak vrátí false a vypíše chybu.
x+ - to samé jako u x, jen s tím, že soubor je možné i číst
c - tento mód je trochu novější a dělá to, že otevře soubor pouze pro zápis, pokud nebude existovat, tak ho vytvoří, ale... pokud bude již existovat, tak ho nezkrátí jako u w a zároveň by neměl vyvolat chybu jako případě s x a je čten od začátku do konce
c+ - to samé jako u c, jen umí soubor i číst
- Jak vidíte, tak módu je celkem dost, stačí si vybrat jaký zrovna potřebujem.
- Třetí a čtvrtý parametr se moc nepoužívá, ani já osobně jsem ho nikdy nepoužil a pochybuju, že ho i vy použijete.
- Třetím parametrem je bool hodnota, pokud chceme použít vložení cesty (výchozí je false) a s tímto parametrem se váže čtvrtý parametr, který určuje zdroj (typ resource), pro zapsání.
- Příklad si nebudem ani uvádět, protože typ
resource zatím neznáme a hlavně je dost malá šance, že se s tím u
fopen() setkáte.
- Další funkci kterou se naučíme bude pro zapsání nějakého textu do souboru a to přes
fwrite() (binárně bezpečný).
- Tato funkce má 3 parametry, kde první je zdroj souboru, druhá je text, co se tam má zapsat a třetí je nepovinná a udává počet znaků.
$soubor = fopen("file.txt", 'w'); // pouzijeme predchozi priklad
fwrite($soubor, "nejaky text"); // zapisem do souboru "nejaky text"
fwrite($soubor, "nejaky text", 6); // zapisem do souboru "nejaky"
- Další funkce bude pro čtení souboru a to
fread().
- Tato funkce má pouze 2 parametry, kde první je opět zdroj souboru a druhý počet znaků (kolik se jich má přečíst).
- Než si ale ukážem příklad, tak je nutné zmínit novou funkci pro zjištění velikosti souboru a to
filesize().
Protože druhý parametr funkce
fread() potřebuje zadat počet znaků, který ten soubor má.
$soubor = fopen("file.txt", 'r'); // pouzijeme predchozi priklad
$vystup = fread($soubor, filesize("file.txt")); // ulozi obsah souboru do promenne
echo $vystup; // vypise
- Vždy je nutné opět soubor zavřít, pokud jsem s ním přestali pracovat a to přes funkci
fclose().
- Tato funkce má jeden parametr pro držení souboru. Takže celý příklad bude vypadat asi takto.
$soubor = "file.txt"; // nazev souboru
$file = fopen($soubor, 'w'); // vytvori soubor
fwrite($file, "ahoj svete"); // zapise text
$vystup = fread($file, filesize($soubor)); // ulozi text ze souboru do promenne
fclose($file); // zavre soubor
echo $vystup; // vypise nacteny text
Práce s ukazatelem v souboru
- Řekneme si něco málo u funkcích, které slouží na pohyb ukazatele v souboru.
- Výše u módů bylo, že určitý parametr čte soubor od začátku do konce nebo obráceně, to znamená, ze ukazatel byl nastaven na začátku a procházel celý soubor až do konce. A my si ukážem, jak měnit pozici toho ukazatele.
- Pokud budeme mít soubor, který bude mít velikost třeba 500MB, tak ho nebudeme přeci procházet celý, ale můžeme si určit pozici (oblast), která se má přečíst a tím zrychlit chod scriptu.
- První funkcí bude fseek(). Tato funkce má 3 parametry, kde první je zdroj souboru, druhý je offset a třetí je mód výběru.
// budeme mit soubor "file.txt", kde bude text "Ahoj svete, jak se mas?"
$soubor = "file.txt";
$file = fopen($soubor, "r"); // otevrem soubor
echo fread($file, filesize($soubor)); // vypise cely text
fseek($file, 12); // nastavime offset o 12 doprava
echo fread($file, filesize($soubor)); // vypisem vse, od offsetu 12 do konce "jak se mas?"
- Druhý parametr může být i záporný offset. Ukázka bude níže.
- Jak už jsem řekl, tak tato funkce má 3 parametry, třetí parametr je tedy mód a módy máme celkem 3 a to:
SEEK_SET - relativní vzdálenost od začátku souboru (výchozí)
SEEK_CUR - relativní vzdálenost od aktuální pozice
SEEK_END - relativní vzdálenost od konce souboru
// pomoci SEEK_SET
fseek($file, 12, SEEK_SET); // nastavime offset o 12 doprava
echo fread($file, filesize($soubor)); // vypisem vse, od offsetu 12 do konce "jak se mas?"
// pomoci SEEK_END
fseek($file, -4, SEEK_END); // nastavime offset az na konec -4 znaky
echo fread($file, filesize($soubor)); // vypisem posledni 4 znaky "mas?"
// SEEK_CUR neni nic jineho, nez pokracovani od aktualni pozice offsetu
- Další funkce je
ftell(), která má jeden parametr a to zdroj souboru.
- Tato funkce vrací hodnotu aktuální pozice v souboru.
echo ftell($file); // vypise 0
fseek($file, 12); // posuneme ukazatel o 12 znaku doprava
echo ftell($file); // vypise 12
fseek($file, 0, SEEK_END); // nastavime na konec
echo ftell($file); // vypise 23
fseek($file, 0, SEEK_SET); // nastavime na zacatek
echo ftell($file); // vypise 0
- K této funkci toho není moc co dodat, tak pojďme na další a to
rewind().
- Tato funkce má opět jeden parametr - zdroje souboru a posouvá ukazatel na začátek souboru.
- Je vlastně stejná jak funkce
fseek() s módem SEEK_SET.
rewind($file); // posune ukazatel na zacatek souboru
fseek($file, 0, SEEK_SET); // to same, jak rewind()
- Ještě bych asi zmínil jednu funkci a to
fgetc(), která vrací znak z ukazatele.
- Tato funkce má jeden parametr a to zdroj souboru.
echo fgetc($file); // vypise znak "A"
- Jak vidíte, tak by jsme museli posouvat vždy pointer o jeden offset doprava, proto je nejlepší možnost použít cyklus.
while (false !== ($znak = fgetc($file)))
{
echo $znak; // vypiseme cely soubor po znakach
}
- Bylo by ještě dobré to ošetřit podmínkou, pokud se soubor opravdu otevřel. Takže před cyklus by jsme přidali:
if (!$file) die("Soubor se nepodařilo otevřít");
- U cyklus si všimněte podmínky. Místo
!=, tam je
!==. Není to chyba, je to nutné!
- Význam to má stejný, ale liší se to v jedné věci. U tohoto operátoru se porovnává i typ, né jen hodnota a funkce
fgetc() to vyžaduje,
protože nevrací pouze bool hodnotu, ale i prázdnou nebo 0.
- Jako poslední funkci by jsme si ukázali
unlink(), která slouží pro mazání souboru a má též jeden parametr a to název souboru.
if (file_exists("file.txt")) // zkontrolujem, zda soubor existuje
{
unlink("file.txt"); // pokud ano, tak ho smazem
}
else echo "Soubor neexistuje!"; // pokud ne, tak vypisem, ze neexistuje
Jiný způsob pro práci se soubory
- PHP má ovšem svoji vlastní funkci pro práci se soubory.
- Jako první vám představim funkci file_put_contents().
- Tato funkce má 4 parametry a dokáže nahradit funkce fopen(), fwrite() a fclose().
- A jak už asi vidíte, tak tato funkce slouží pro zápis textu do souboru a nejenom to... pokud soubor neexistuje, tak ho i vytvoří nebo existující přepíše.
- Pojďmě si tedy vysvělit parametry. První je název souboru, druhý text, který chceme zapsat do souboru, třetí je flag a čtvrtý zdroj.
Kde se čtvrtým parametrem za zatím zabývat nebudem.
file_put_contents("file.txt", "bagr"); // vytvorime soubor "file.txt" s textem "bagr"
- Jednoduché že? Teď se podíváme na třetí parametr a to flagy:
FILE_USE_INCLUDE_PATH - hledá soubor v adresáři
FILE_APPEND - pokud soubor bude existovat, tak text pripoji k existujicimu (místo přepsání)
LOCK_EX - zamkne soubor při zápisu - to znamená, že v jednu chvíli do souboru může zapisovat jen jeden
- Flagy lze spojovat pomocí
|, takze není problém spojit třeba FILE_APPEND a LOCK_EX.
// pokud znovu zavolame funkci, tak v souboru "file.txt" budeme mit "bagrbagr"
file_put_contents("file.txt", "bagr", FILE_APPEND);
// muzeme tez spojit 2 flagy misto jednoho, nyni to bude pridavat text do souboru a
// pristupovat k souboru bude moct ve stejny cas pouze jednou
file_put_contents("file.txt", "bagr", FILE_APPEND | LOCK_EX);
- To by bylo k zápisu a teď funkce pro čtení
file_get_contents().
- Tato funkce je trochu obsáhlejší, obsahuje 5 parametrů. Nás bude zajímat hlavně ten první a tak trochu poslední 2.
- Protože druhý parametr je flag
FILE_USE_INCLUDE_PATH, který moc používat nebudem, tak místo něj budeme psát
null.
- Třetí parametr slouží opět ke
zdroji kontextu, ten též používat nebudem, tak opět
null.
echo file_get_contents("file.txt"); // vypise obsah souboru "file.txt" - u nas "bagr"
- Jak už jsem řekl, tak 2. a 3. parametr přeskočíme, takže 4. parametr je pro offset, který snad už nemusim vysvětlovat a poslední parametr je délka offsetu.
Ta značí, kolik znaků od offsetu se má přečíst.
echo file_get_contents("file.txt", null, null, 2); // vypise "gr" (ze 4 znaku posledni 2)
// vypise "ag", protoze ukazatel je na 1 a cteme do znaku 2.. opet ze slova "bagr"
echo file_get_contents("file.txt", null, null, 1, 2);
// pokud budeme chtit vypsat posledni 2 znaky, tak to muzeme opet takto - "gr"
echo file_get_contents("file.txt", null, null, filesize("file.txt") - 2, 2);
Dobrovolný domácí úkol
1) Vytvořte si proměnnou s nějakým textem aspoň o 10 znacích a každý znak převeďte na dec. číslo a poté ho zapište do souboru a každý znak v souboru odděl mezerou nebo čárkou.
$text = "Super web o PHP!"; // nas text
for ($i = 0; $i < strlen($text); $i++) // prochazi jednotlive znaky
{
file_put_contents("file.txt", ord($text[$i])." ", FILE_APPEND); // zapisuje dec. cisla
}
2) Vytvořte si matici 3x3 s čísli od 1-9. Nyní do souboru zapište tuto matici, ale aby vzhledově vypadala jako matice. A použijte běžnou metodu přes fopen() a fwrite().
Pozor na to, aby ze koncem každého řádku nebyl žádný znak (poslední znak číslo).
// pole matice
$mat = array(
0 => array(1, 2, 3),
1 => array(4, 5, 6),
2 => array(7, 8, 9)
);
$f = fopen("file.txt", "w"); // vytvori soubor
for ($i = 0; $i < count($mat); $i++) // prochazi radky
{
for ($j = 0; $j < count($mat[$i]); $j++) // sloupce
{
fwrite($f, $mat[$i][$j]); // zapisuje cisla
if ($j != count($mat) - 1) fwrite($f, "\t"); // pridava tabulator
}
fwrite($f, "\n"); // prida odradkovani
}
fclose($f);
3) Teď uděláme opak. Máme soubor
matice.txt, kde je matice 4x4 (viz. níže) a přečteme pouze prvky na hlavní diagonále.
Takže neprocházet celou matici, jen ty prvky. Použijeme opět klasické funkce
fopen() apod. Poté sečteme hlavní diagonálu a dopíšeme do souboru její součet.
- Obsah souboru
matice.txt bude:
6 7 8 2
3 1 4 9
7 8 0 2
2 1 8 9
$f = fopen("matice.txt", "r+"); // nacte soubor pro cteni i zapis
$sum = $offset = 0; // nastavi pomocne promenne na 0
for ($i = 0; $i < 4; $i++) // projde 4x, protoze matice je 4x4
{
rewind($f); // vrati offset na zacatek
fseek($f, $offset); // posouva ukazatel
$sum += fread($f, 1); // scita hl. diagonalu
$offset += 11; // zvysuje offset
}
fwrite($f, "\nSuma: ".$sum); // dopise sumu do souboru
fclose($f); // zavre soubor
- Soubor po úpravě.
6 7 8 2
3 1 4 9
7 8 0 2
2 1 8 9
Suma: 16