PHP/System plików: Różnice pomiędzy wersjami

Usunięta treść Dodana treść
Nie podano opisu zmian
 
Linia 9:
Zawartość pliku można odczytać w PHP na kilka sposobów. Oto pierwszy z nich, wywodzący się jeszcze z języka C:
 
<sourcesyntaxhighlight lang="php"><?php
// 1.1 - Tworzymy odwołanie do pliku
$_Uchwyt = fopen('plik.txt', 'r');
Linia 23:
fclose($_Uchwyt);
?>
</syntaxhighlight>
</source>
 
Każdy dostęp do pliku musi rozpocząć się od jego otwarcia. Zadaniem tym zajmuje się funkcja ''fopen()''. Parametr '''r''' nakazuje otwarcie pliku do odczytu. Następnie w pętli pobieramy plik po kawałkach o wielkości jednego kilobajta. W ten sposób dane mogą być przetwarzane "równolegle" z odczytem. Funkcja ''feof()'' służy do sprawdzenia, czy osiągnęliśmy koniec pliku. Po zakończonej pracy nasze połączenie z plikiem trzeba zamknąć. Odpowiada za to ''fclose()''.
Linia 31:
Z powyższego kodu możemy wyrzucić pętlę i pobrać wszystko za jednym zamachem. Wystarczy tylko użyć funkcji ''filesize()'', aby podała nam rozmiar pliku:
 
<sourcesyntaxhighlight lang="php"><?php
// 1.1 - Otwieramy
$_Uchwyt = fopen('plik.txt', 'r');
Linia 41:
fclose($_Uchwyt);
 
?></sourcesyntaxhighlight>
 
Zwróćmy uwagę na jakość podanych przykładów. Zmień nazwę plików, do których się odwołujemy, na jakiś nieistniejący. Oba skrypty wtedy zgłupieją. Pierwszy zaleje nas falą ostrzeżeń przez 30 sekund (potem przestaną się pojawiać), drugi zrobi ich "tylko" kilka (przyczyną jest brak pętli). Dlatego powinniśmy tak przygotować wszystko, abyśmy sami panowali nad komunikatami. Czas stworzyć prymitywną obsługę błędów. Wykorzystamy tutaj operator '''@''', aby zagłuszyć funkcję ''fopen()'' i sprawdzić zwracany wynik. Powinna ona zwrócić nam połączenie z plikiem, tj. wartość typu ''Resource''. Zobaczmy:
 
<sourcesyntaxhighlight lang="php"><?php
// 1.1 - Otwieramy plik, alarmujemy w wypadku błędu
$_Uchwyt = @fopen('inny_plik.txt', 'r') or die('Wystąpił błąd.');
Linia 52:
// 1.3 - Zamykamy
fclose($_Uchwyt);
?></sourcesyntaxhighlight>
 
{{Uwaga|Jeśli skrypt odczytujący zacznie się dziwnie zachowywać, pierwszym krokiem powinno być tymczasowe usunięcie operatora '''@''' - inaczej nigdy nie dowiesz się, co jest przyczyną problemów!}}
Linia 60:
Od PHP 4.3.0 nie trzeba już rozpisywać się, aby wczytać zawartość pojedynczego pliku. Cała czynność jest zautomatyzowana w funkcji ''file_get_contents()''. Aby tu sprawdzić poprawność otwarcia, wystarczy porównać zwrócony wynik z wartością '''false''', która jest zwracana w przypadku błędu:
 
<sourcesyntaxhighlight lang="php"><?php
// 1.1 - Otwieramy, czytamy i zamykamy
$_TrescPliku = @file_get_contents('plik.txt') or die('Wystąpił błąd.');
Linia 66:
// 1.2 - Zwracamy treść pliku
echo $_TrescPliku;
?></sourcesyntaxhighlight>
 
Pisząc księgę gości, poznaliśmy funkcję ''file()'', która zwracaną zawartość rozbijała od razu na tablicę poszczególnych linijek. Dzięki tej właściwości wyświetlimy plik jako listę wypunktowaną HTML bez większych trudności:
 
<sourcesyntaxhighlight lang="php"><?php
// 1.1 - Otwieramy plik i czytamy go do tablicy
$_TrescPliku = @file('plik.txt') or die('Wystąpił błąd.');
Linia 84:
// 1.4 - ...i zamykamy listę.
echo '</ul>';
?></sourcesyntaxhighlight>
 
Pamiętaj, że ''file()'' nie gubi znaków końca linii - te są nadal zapisane w poszczególnych linijkach. Dlatego gdy będziesz chciał z powrotem połączyć wszystko w całość, powinieneś napisać
 
<sourcesyntaxhighlight lang="php">implode("", $_TrescPliku);</sourcesyntaxhighlight>
 
zamiast np.
 
<sourcesyntaxhighlight lang="php">implode("\n", $_TrescPliku);</sourcesyntaxhighlight>
 
Pod żadnym pozorem nie odczytuj plików w ten sposób:
 
<sourcesyntaxhighlight lang="php">implode('', file('plik.txt'));</sourcesyntaxhighlight>
 
Sens takiego kodu można streścić w prostym porównaniu: pakować się tylko po to, by się natychmiast rozpakować. Nie służy to niczemu, a konsumuje niezbędny czas. Aby przekonać się, jak mało wydajne jest takie rozwiązanie, spróbuj załadować tak plik tekstowy o wielkości megabajta, następnie powtórz to samo z wykorzystaniem ''file_get_contents()'' i porównaj wrażenia.
Linia 104:
Powinniśmy jeszcze wspomnieć o rozwiązaniu tzw. "wg pana od informatyki" (aczkolwiek bardzo go szanujemy). Rozwiązanie najlepiej pokazać na przykładzie:
 
<sourcesyntaxhighlight lang="php"><?php
// 1.1 - Inicjacja zmiennej
$_Plik='plik.txt';
Linia 124:
}
// Tutaj dalsze operacje na pliku
?></sourcesyntaxhighlight>
 
Metoda na "pana nauczyciela" polega na pełnym obsłużeniu wszystkich możliwości jakie mogą wystąpić podczas czytania pliku oraz posłużenia się funkcjami typu file_exists(). Wadą takiego rozwiązania jest jednak to, że pisząc kod możemy zakopać się w blokach ''if'' gubiąc główny wątek programu, a także nie jesteśmy w stanie wymyślić wszystkich możliwych sytuacji, które mogą się zdarzyć.
Linia 133:
Zapis danych wygląda analogicznie do odczytu. Różne jest tylko miejsce docelowe danych. Sposób pierwszy polega na otwarciu pliku funkcją ''fopen()'' i skorzystaniu z ''fwrite()'' do dodania nowej zawartości. Plik otwieramy z parametrem ''w'' (nadpisujemy starą zawartość) lub ''a'' (dopisujemy coś do pliku). W przypadku operowania danymi binarnymi, dodajemy jeszcze literę ''b''.
 
<sourcesyntaxhighlight lang="php"><?php
// 1.1 - Otwieranie
$_Plik = fopen('./plik.txt', 'w');
Linia 141:
fclose($_Plik);
 
?></sourcesyntaxhighlight>
 
Po uruchomieniu tego skryptu w ''plik.txt'' powinna pojawić nam się nowa zawartość. W przypadku pracy na systemie Linux/Unix sprawdź, czy PHP ma uprawnienia do edycji plików w twoim katalogu roboczym.
Linia 147:
W PHP 5.0.0 pojawiła się funkcja ''file_put_contents()'', która upraszcza całą sprawę. Zwraca ona liczbę zapisanych do pliku bajtów i możemy wykorzystać to do kontroli, czy operacja dopisywania faktycznie się udała. Funkcja pobiera dwa parametry: nazwę pliku oraz tekst do wpisania i "firmowo" nie zniekształca danych binarnych.
 
<sourcesyntaxhighlight lang="php"><?php
// 1.1 - Jeśli zapis się powiódł wyświetl komunikat o powodzeniu
if(file_put_contents('./plik.txt', 'To jest nowa zawartość pliku') != 0)
Linia 154:
}
 
?></sourcesyntaxhighlight>
 
Zadajmy sobie pytanie, co jeśli musimy dopisać dodatkową treść. Naturalnie ''file_put_contents()'' także to potrafi. Trzeba tylko skorzystać z trzeciego parametru, w którym możemy ustawiać flagi. ''FILE_APPEND'' jest tym, czego potrzebujemy.
 
<sourcesyntaxhighlight lang="php"><?php
// 1.1 - Jeśli zapis się powiódł wyświetl komunikat o powodzeniu
if(file_put_contents('./plik.txt', 'Dopisana treść', FILE_APPEND) != 0)
Linia 165:
}
 
?></sourcesyntaxhighlight>
 
Ten skrypt będzie już dopisywać dane do pliku, zamiast je nadpisywać.
Linia 184:
Przy korzystaniu z nich musimy pamiętać o wydajności. Odczyt wszelkich danych z dysku jest dość powolny, dlatego starajmy się jak najwięcej wycisnąć z pojedynczego wywołania funkcji. Oto przykład: załóżmy, że mamy plik ''A.txt'' i na jego podstawie generujemy ''B.txt'' zawsze, kiedy ulegnie on zmianie (taki kompilator). Musimy zatem napisać mechanizm sprawdzający, czy można uruchomić kompilację, czy też jest ona zbędna.
 
<sourcesyntaxhighlight lang="php"><?php
 
if(!file_exists('A.txt'))
Linia 207:
}
 
?></sourcesyntaxhighlight>
 
Pozornie wszystko wygląda na poprawne - skrypt prawidłowo raportuje wszystkie sprawy. Jednak robi to zbyt wolno, gdyż przeciążyliśmy go dużą ilością odwołań do dysku twardego. Jeżeli uruchomimy go na witrynie z dużym ruchem, osiągnąłby gorsze wyniki wydajności, niż inne skrypty. Spróbujmy go nieco zmodyfikować. Czy naprawdę potrzebujemy funkcji ''file_exists()''? Okazuje się, że nie. Przecież ''filemtime()'' zwróci nam '''false''', jeżeli plik nie będzie istniał i możemy to wykorzystać. Oto poprawiony kod skryptu:
 
<sourcesyntaxhighlight lang="php"><?php
 
$czasA = @filemtime('A.txt');
Linia 240:
}
 
?></sourcesyntaxhighlight>
Zauważmy, w tym przypadku mamy tylko dwa odwołania do dysku, a jeśli plik ''A.txt'' nie będzie istnieć, to nawet jedno! Zamiast wykonywania za każdym razem setek nowych funkcji, wykorzystujemy maksymalnie te dane, które już mamy. To jest właściwa filozofia przy pracy z plikami.