Kirjautuminen

Haku

Tehtävät

Opasarkisto: Käytännön PHP-opas: Osa 5 - Tiedostojen käsittely

  1. Osa 1 - Johdanto
  2. Osa 2 - Muuttujat ja taulukot
  3. Osa 3 - Komentorakenteet
  4. Osa 4 - PHP ja Internet-sivut
  5. Osa 5 - Tiedostojen käsittely
  6. Osa 6 - Funktiot
  7. Osa 7 - Evästeet ja istunnot
  8. Osa 8 - Tietokannat (MySQL)
  9. Osa 9 - Vinkkejä ja vihjeitä

Kirjoittaja: Antti Laaksonen. Vuosi: 2003.

Huomio! Tämä opas on vanhentunut. Oppaan sisältöön ei voi enää luottaa. Opas on säilytetty vain sen historiallisen arvon vuoksi.

PHP-skripti suoritetaan palvelimella, minkä ansiosta sillä on pääsy myös palvelimen tiedostoihin. Tämä opas käsittelee tiedostojen lukemista ja kirjoittamista. Oppaassa tutustutaan myös pariin käyttökelpoiseen tiedostofunktioon sekä menetelmään hakemiston kaikkien tiedostojen läpikäymiseen.

Tiedoston lukeminen taulukkoon

Helppo tapa lukea tiedostosta rivejä on lukea rivit taulukkoon file-funktiolla. Funktio palauttaa taulukon, joka sisältää tiedoston rivit nollasta alkaen. Esimerkissä tiedosto testi.txt sisältää kolme riviä.

<?php
//luetaan tiedosto taulukkoon $tiedosto
$tiedosto = file("testi.txt");

//nyt:
// $tiedosto[0] = "Ensimmäinen rivi."
// $tiedosto[1] = "Toinen rivi."
// $tiedosto[2] = "Kolmas rivi."
// count($tiedosto) = 3

//tulostetaan rivit
for ($i = 0; $i < count($tiedosto); $i++) {
   echo ($i + 1) . ": " . $tiedosto[$i];
}
?>

Luettava tiedosto voi olla myös toisella palvelimella. Tällöin file-funktion parametriksi annetaan tiedoston koko URL, kuten http://www.palvelin.fi/sivu.htm. Taulukon alkiot päättyvät rivinvaihtomerkkiin, mikä voi välillä tuottaa ongelmia esimerkiksi merkkijonojen vertailussa. Funktio trim poistaa ylimääräiset rivinvaihdot merkkijonon lopusta.

Tiedoston avaaminen ja sulkeminen

Jos pelkkä lukeminen taulukkoon ei riitä tai tiedostoon halutaan kirjoittaa, tiedosto on avattava fopen-funktiolla. Funktio palauttaa tiedostotunnisteen, jota käytetään myöhemmin avattuun tiedostoon liittyvien operaatioiden yhteydessä. Tiedosto voi olla, samoin kuin file-funktion kanssa, myös URL-osoite. Vastaavasti fclose sulkee avatun tiedoston.

Tiedostosta lukeminen

Jos tiedostosta halutaan lukea, se avataan tilassa "r" (read). Funktio fgets lukee seuraavan rivin tiedostosta. Funktion toinen parametri on rivin maksimipituus. Jos tiedoston rivien määrää ei tiedetä, kannattaa tarkistaa funktiolla feof ennen jokaista lukukertaa, että rivejä on vielä jäljellä.

<?php
//avataan tiedosto lukutilassa
$tt = fopen("testi.txt", "r");

//nollataan rivinumerolaskuri
$i = 0;

//luetaan rivejä, kunnes tiedosto loppuu
while (!feof($tt)) {
   //luetaan seuraava rivi muuttujaan
   $rivi = fgets($tt, 1024);
   //tulostetaan rivi rivinumeron kanssa
   echo "$i: $rivi";
   //kasvatetaan laskuria
   $i++;
}

//suljetaan tiedosto
fclose($tt);
?>

Tiedostoon kirjoittaminen

Jos tiedostoon halutaan kirjoittaa, se avataan tilassa "w" (write). Jos tiedostoa ei ole olemassa, se luodaan. Jos tiedosto on jo olemassa, se tyhjennetään. Tiedoston voi avata myös tilassa "a" (append), jolloin kirjoittaminen aloitetaan tiedoston lopusta ja tiedoston vanha tieto ei katoa. Tämän jälkeen tiedostoon voi kirjoittaa funktiolla fwrite.

<?php
//avataan tiedosto kirjoitustilassa
$tt = fopen("testi2.txt", "w");

//kirjoitetaan tiedostoon kolme riviä; \n tarkoittaa rivinvaihtoa
fwrite($tt, "Rivi 1\n");
fwrite($tt, "Rivi 2\n");
fwrite($tt, "Rivi 3");

//suljetaan tiedosto
fclose($tt);
?>

Tiedoston oikeudet

Unix-käyttöjärjestelmässä tiedoston oikeudet (chmod) voivat rajoittaa sen lukemista tai kirjoittamista. Sopiva chmod-arvo riippuu siitä, onko tiedostoa tarkoitus vain lukea vai pitääkö siihen pystyä myös kirjoittamaan. Virheilmoitus "Permission denied" viestii liian tiukoista oikeuksista. FTP-ohjelma sisältää tavallisesti mahdollisuuden muuttaa tiedoston oikeuksia. PHP:stä löytyy myös funktio chmod tähän tarkoitukseen.

Rivinvaihto-ongelmat

Unixeissa ja Windowseissa käytetään erilaista rivinvaihtoa. Unixin rivinvaihto on \n (ASCII 10), kun taas Windowsin rivinvaihto on \r\n (ASCII 13 + ASCII 10). Tämä voi tuottaa ongelmia silloin, kun skriptin luomaa tiedostoa yritetään lukea Windowsin tekstieditorilla: toiset editorit eivät tunnista oikein Unix-rivinvaihtoja. Yhtä kaikki PHP:lle kelpaavat molemmat tavat ilmaista rivinvaihto.

Tiedoston tiedot

PHP sisältää joukon valmiita funktioita, joiden avulla on mahdollista saada tarkempia tietoja tiedostosta. Funktiot ovat käytössä ainoastaan oman palvelimen tiedostoilla. Tässä listassa on muutamia tavallisimpia funktioita.

Esimerkki tarkistaa tiedoston olemassaolon ja tulostaa sen koon ja muokkausajan. Lisätietoa date-funktion käytöstä on tulossa opassarjan seuraaviin osiin.

<?php
//käsiteltävä tiedosto
$tiedosto = "testi.txt";

//jatketaan, jos tiedosto on olemassa
if (file_exists($tiedosto)) {
   //luetaan tiedoston koko ja muokkausaika muuttujiin
   $koko = filesize($tiedosto);
   $aika = filemtime($tiedosto);
   //tulostetaan tiedot
   echo "Tiedoston koko on $koko tavua ja sitä on viimeksi muokattu " . date("d.m.Y", $aika). ".";
} else {
   echo "Tiedostoa ei ole olemassa!";
}
?>

Hakemiston tiedostojen läpikäyminen

Hakemiston tiedostojen läpikäyminen onnistuu kolmen funktion yhteistyöllä: opendir, readdir ja closedir. Näitä funktioita tarvitaan vaikkapa silloin, kun halutaan luoda hakemistossa olevista kuvatiedostoista automaattisesti päivittyvä kuvagalleria. Aluksi kutsutaan opendir-funktiota parametrina käsiteltävä hakemisto. Tämän jälkeen readdir-funktio palauttaa aina seuraavan tiedoston hakemistossa. Lopuksi funktio closedir sulkee hakemiston.

<?php
//avataan hakemisto kuvat
$hak = opendir("kuvat/");
//luetaan ensimmäisen tiedoston nimi
$nimi = readdir($hak);

//jatketaan niin kauan kun $nimi ei ole false
while ($nimi) {
   //tulostetaan tiedoston nimi
   echo "$nimi\n";
   //luetaan seuraavan tiedoston nimi
   $nimi = readdir($hak);
}

//suljetaan hakemisto
closedir($hak);
?>

Jos opendir-funktiota kutsutaan parametrilla ".", tiedostoja etsitään siitä hakemistosta, johon skripti on tallennettu (tai oletushakemistosta). Hakemistosta luetaan sekä tiedostot että alihakemistot: funktio is_file ilmoittaa, jos kyseessä on tiedosto ja is_dir ilmoittaa, jos kyseessä on hakemisto.

Loppusanat

Tiedostofunktiota tarvitsee usein ja niiden käytöstä tuleekin nopeasti arkipäivää PHP-ohjelmoijalle. PHP:n manuaalia kannattaa silmäillä tiedostoihin(kin) liittyvissä asioissa: se sisältää kaikkien tiedostofunktioiden kuvaukset ja myös monia hyödyllisiä esimerkkiskriptejä.

Näillä näkymin oppaita tulee vielä kaksi tai kolme. Vielä käsittelemättä olevia aiheita ovat ainakin funktiot ja luokat, merkkijono- ja päivämääräfunktiot, evästeet sekä MySQL-tietokannan käyttäminen. Seuraava opas ilmestynee parin-kolmen viikon kuluessa.

Antti Laaksonen, 24.4.2003


Kommentit

mikaelh [24.04.2003 19:33:25]

Lainaa #

opendir(), readdir() ja closedir() yhdistelmän sijasta on helpompi käyttää vain glob()-funktiota. :)

Antti Laaksonen [25.04.2003 01:31:10]

Lainaa #

Näyttää olevan version 4.3.0 ominaisuuksia, enpä olekaan huomannut moista. Selvästi näppärämpi tapa. Olkoon tässä oppaassa kuitenkin tuo vanhempi yhteensopivuuden vuoksi.

Tumpi [25.04.2003 15:58:59]

Lainaa #

Ihan hyvä, mutta vielä ku oisit pistäny yksittäisten rivien käsittelyä...

Gwaur [27.04.2003 01:07:15]

Lainaa #

Niin, kun mulla on jäänyt tuo tietyn rivin muuttaminen vähän epäselväksi...
Esim. jos tiedostossa on rivejä vaikka neljä, ja niissä lukee:

Moi!
Olen Saasta!
Käyn ohjelmointiputkassa aika usein!
Heippa!

Niin haluan korvata kolmannen rivin vaikka muotoon: "Käyn ohjelmointiputkassa tosi usein!". haluan sen siis korvata niin, ettei sillä tekstillä ole mitään väliä, kun Tumpi joskus jotain semmoista ehdotti että

if ($rivi == "Käyn ohjelmointiputkassa aika usein") {

mutta jos kolmannella rivillä onkin jotain aivan muuta? Pitääkö sen olla jotenkin tyyliin:

if ($rivi == 3) {

tai jotain...?

Tai no.. miksei joku voisi samantien tehdä sille jotain yksinkertasta funktiota, vaikka tyyliin

row_replace($tt, 3, "Käyn ohjelmointiputkassa tosi usein!");

eli tossa on käytössä toi fopen():lla aukaistu tiedosto, $tt, josta korvatan kolmas rivi tekstillä "Käyn ohjelmointiputkassa tosi usein!".

PS: Tais tulla vähän pitkä...
PPS: phpkoodi-tagin hyötykäyttöä :)

Gwaur [27.04.2003 01:31:27]

Lainaa #

Onko tossa phpkoodi-tagissa kenties joku pituusrajoitin tai jotain? ainakin mun koneella toi loppuu hieman lyhyeen...

Tumpi [03.05.2003 12:57:36]

Lainaa #

Niin, putkasssa aina tuppaa koodivinkeistä jäädä pari viimeistä merkkiä pois... ja näköjään nyt tästäkin.

(nimetön) [14.06.2003 03:14:52]

Lainaa #

<?php

$tiedosto = file("tiedosto.txt");
$tiedosto[2] = "uusi rivi\n";

$fo = fopen("tiedosto.txt", "w");
 foreach($tiedosto as $rivi) {
  fputs($fo, $rivi);
 }
fclose($fo);

?>

tämä koodi korvaa tiedoston "tiedosto.txt" kolmannen rivin sanalla "uusi rivi".

jonsku [31.01.2004 04:18:28]

Lainaa #

miten tossa ekassa esimerkissä saa ne eri riveille ja ne numerot pois alusta??

jonsku [31.01.2004 04:33:13]

Lainaa #

sain numerot pois... mut mite ne saa eri riveille

jonsku [31.01.2004 11:14:12]

Lainaa #

nyt sain toimimaa beeärrällä :)

masuli [06.05.2004 20:42:12]

Lainaa #

voiks ton fwrite käskyn perään laittaa muuttujia
esim. fwrite($tt, $uusirivi"\n");

dera [15.05.2004 11:45:14]

Lainaa #

Voi kai

tsuriga [02.12.2004 16:53:09]

Lainaa #

Kyllä voi, koodin tulkkausvaiheessa haetaan muuttujan arvo ja käytetään sitä funktion parametrina.

McGordon [04.06.2005 09:20:42]

Lainaa #

Jiihaa! Vihdoin opin tiedostoon kirjoittamisen! KIITOS TÄSTÄ OPPAASTA!

DjAS [28.10.2005 21:47:43]

Lainaa #

Opin tiedostoon kirjoittamisen, mutta miten se hoituisi esimerkiksi palautelomaketta hyväksikäyttäen?

Utzo [07.01.2006 16:43:14]

Lainaa #

Opin tiedostoon kirjoittamisen, mutta miten se hoituisi esimerkiksi palautelomaketta hyväksikäyttäen?

<html>
<head>
</head>
<body>
<form action="tiedostosi.php" method="POST">
<input type="text" value="tekstiä" name="nimi">
<input type="submit" value="Tulosta nimi">
</form>

<?php
//Otetaan lomakkeesta muuttujat ylös
$nimi = $_POST['nimi'];
//Nyt kirjotettattaisiin $nimi tiedostoon.
?>
</body>
</html>

miiro [11.02.2006 19:58:11]

Lainaa #

Olisiko whilen sijasta käytännöllisempää käyttää foria?

EgeTheGod [06.03.2006 15:42:49]

Lainaa #

Tämän ansiosta ratkasin monta viikkoa kiusanneen ongelman :). Hyvä opas!

Juhko [23.11.2006 19:35:25]

Lainaa #

Utzo kirjoitti:

Opin tiedostoon kirjoittamisen, mutta miten se hoituisi esimerkiksi palautelomaketta hyväksikäyttäen?

<?php
// luetaan nimi
$nimi = $_POST['nimi'];
//avataan tiedosto kirjoitustilassa
$tt = fopen("testi2.txt", "w");

//kirjoitetaan tiedostoon kolme riviä; \n tarkoittaa rivinvaihtoa
fwrite($tt, "$nimi\n");

//suljetaan tiedosto
fclose($tt);
?>

Väpä [17.02.2007 14:14:16]

Lainaa #

Toi kuvagalleria ei oo mikään toimivin ratkaisu koska se tulostaa sivulle pelkän kuvan nimen.

jaatinen [28.03.2007 13:01:31]

Lainaa #

Miten toi tiedostosta hakeminen tehään niin, ettei se lue alihakemistojen nimiä ollenkaan?

Raketti [17.05.2007 19:16:53]

Lainaa #

Miten tuon kuvagallerian saisi toimimaan jos joku tietää koodin niin vosiko panna tänne vaikka voinhan sen itsekin opetella mutta se oli kuitenkin nopeampaa.

bartfast [26.07.2007 21:05:22]

Lainaa #

En kyllä arvosta tuota asennetta, mutta jospa innostuisit itse opettelemaan lisää vaikkapa tämän koodinpätkän innoittamana. Yksinkertaisuudessaan saat hakemiston kaikki kuvat näkyviin www-sivuille esim. seuraavalla skriptillä:

<?php
foreach(glob("*.jpg") as $filename) {
	echo "<img src={$filename} /><br />";
}
?>

Siitä sitten vaan jalostamaan. Kuvista kannattaa näyttää thumbnailit ja jos kuvia on paljon niin sivuuttaa ne.

apsu [05.07.2008 06:44:27]

Lainaa #

Jos teen profiili.php ja laitan kaikkia profiilit samaan tiedostoon tällä tavalla:
nro|nimi|ikä|kommentti
1|ville|70|Mun nimi on Ville ja mä oon 70v!
2|kalle|12|Mä oon Kalle.
3|ralle|11|Olen melkein 12.
...
niin miten kalle voi vaihtaa kommentiaan? Elikkä miten mä vaihan rivin nro. 2 kommenttia?

dartvaneri [13.12.2010 19:28:22]

Lainaa #

Moro!
Voisiko joku auttaa minua? ongelmana on se että tämä ko. koodi toimii kyllä muuten mutta tiedostoon ei tule yhtään mitään:

<!-- laheta.php -->
<?php

$olemassa = file_exists("testi.php");
if($olemassa) {

$tiedosto = fopen("testi.php", "w");

$text = $_POST['teksti'];



fwrite($tiedosto, "$text");

fclose($tiedosto);

header("Location: index.php?sivu=tiedostot");
}
else
echo "Tiedostoa ei löydy";

?>
<!--testi.php-->

<form action="laheta.php" method="post">
<textarea name="teksti" rows="10" cols="70"></textarea>
<input type="submit" value="Laheta">
</form>

Ja testi.php:n oikeudet 664.

Mikä on vikana, ku tohon teksti kenttään kirjoittaa, niin se teksti ei tallennu? ku se kuitenkin ohjaa sen tonne tiedostot.php:hen?

Edit. Nyt toimmi, ku laitoin oikeudet 777 mutta mitä se vaatii että voi php tiedostoon kirjoittaa?

HoxTop [19.12.2010 19:39:47]

Lainaa #

miten saan sivuni menevän toiseen dokumenttiin ilman, että sivuilla olija painaa jostain linkistä?

ErroR++ [16.04.2011 18:59:13]

Lainaa #

Hei kuulkaas, laittakaa ne koodit kooditagien sisään. Selkeytyy aika paljon.

Kirjoita kommentti

Huomio! Kommentoi tässä ainoastaan tämän oppaan hyviä ja huonoja puolia. Älä kirjoita muita kysymyksiä tähän. Jos koodisi ei toimi tai tarvitset muuten vain apua ohjelmoinnissa, lähetä viesti keskusteluun.

Muista lukea kirjoitusohjeet.
Tietoa sivustosta