Obsługa plików


Otwieranie i zamykanie plików

Wszystkie funkcje obsługi plików (oprócz tej otwierającej plik) jako parametr pobierają tak zwany wskaźnik do pliku (file pointer). Jest zmienna jednoznacznie określająca otwarty plik. Skrypt może bowiem otworzyć jednocześnie wiele plików i na wszystkich pracować.

Wskaźnik do pliku zwracany jest przez funkcję fopen(nazwa_pliku, tryb). Drugi parametr określa tryb otwarcia pliku. Tryb należy dobrać odpowiednio do operacji, które będą na pliku przeprowadzane. Możliwe tryby to:

  • r‘ – plik tylko do odczytu; wewnętrzny wskaźnik pliku umieszczany jest na początku pliku,
  • r+‘ – plik do odczytu i zapisu; wewnętrzny wskaźnik pliku umieszczany jest na początku pliku,
  • w‘ – plik tylko do zapisu; wewnętrzny wskaźnik pliku umieszczany jest na początku pliku; zawartość pliku jest niszczona (długość pliku jest zmieniana na zero); jeśli plik nie istnieje PHP próbuje go stworzyć,
  • w+‘ – plik do odczytu i zapisu; wewnętrzny wskaźnik pliku umieszczany jest na początku pliku; zawartość pliku jest niszczona (długość pliku jest zmieniana na zero); jeśli plik nie istnieje PHP próbuje go stworzyć,
  • a‘ – plik tylko do zapisu; wewnętrzny wskaźnik pliku umieszczany jest na końcu pliku; jeśli plik nie istnieje PHP próbuje go stworzyć,
  • a+‘ – plik do odczytu i zapisu; wewnętrzny wskaźnik pliku umieszczany jest na końcu pliku; jeśli plik nie istnieje PHP próbuje go stworzyć.

Pozycja “wewnętrznego wskaźnika pliku” określa, w którym miejscu nastąpi zapisywanie danych do pliku. Jeśli jest na końcu, to dane są dopisywane do poprzedniej treści pliku.

Proste otwarcie pliku do odczytu może wyglądać tak:

<? 

$fp = fopen('dane.txt', 'r');

?>
Zmienna $fp zawiera teraz wskaźnik do pliku dane.txt. Wskaźnik ten trzeba będzie przekazać każdej funkcji, która w jakiś sposób operuje na tym pliku.

 

Otwarty plik możesz chcieć zamknąć. Jeśli nie zamkniesz go ręcznie, to PHP zrobi to za Ciebie po zakończeniu działania skryptu. Gdy w jednym skrypcie zamierzasz zapisać dane do pliku, a następnie je odczytać, musisz najpierw zamknąć plik. Do zamknięcia pliku służy funkcja fclose(wskaźnik).

Wewnętrzny wskaźnik pliku

Wewnętrzny wskaźnik pliku wskazuje miejsce w pliku oznaczające “bieżącą lokalizację” – czyli miejsce, w którym zacznie się kolejna operacja pisania lub czytania. Większość funkcji, które operują na plikach powoduje przesunięcie tego wskaźnika – dla przykładu, każde zapisanie i odczyt z pliku powodują przesunięcie.

Przesunięcie wewnętrznego wskaźnika pliku można wymusić – na przykład, aby rozpocząć czytanie od pewnego miejsca lub żeby pominąć jakiś fragment danych. Służy do tego funkcja fseek(wskaźnik, przesunięcie [typ_przesunięcia]).

Jak widać, pobiera ona dwa obowiązkowe argumenty i jeden opcjonalny. Pierwszy argument to wskaźnik pliku – funkcja musi wiedzieć, w którym pliku ma przesuwać wskaźnik. Drugi to numer znaku, na który ma zostać przesunięty wskaźnik. Ostatni określa typ przesunięcia (możliwe wartości to: SEEK_SET, SEEK_CUR i SEEK_END). Domyślną wartością jest SEEK_SET. Oznacza ona, że wewnętrzny wskaźnik pliku zostanie ustawiony na podanej pozycji.

Wartość SEEK_CURR spowoduje, że wskaźnik pliku zostanie przesunięty od bieżącego miejsca o liczbę znaków określoną przez argument przesunięcie. Natomiast wybranie typu SEEK_END spowoduje, że wskaźnik zostanie ustawiony tyle znaków za końcem pliku, ile określono w argumencie przesunięcie. Istnieje również funkcja rewind(wskaźnik), która przesuwa wewnętrzny wskaźnik pliku na początek.

Odczyt z plików

Odczyt z pliku może być przeprowadzany na kilka sposobów. Opiszemy dwa najpopularniejsze.

Pierwszy to “niskopoziomowe” czytanie danych z pliku za pomocą funkcji fread(wskaźnik, długość). Czyta ona dane z pliku, określonego przez utworzony wcześniej wskaźnik. Ilość odczytanych danych zależy od drugiego argumentu. Jeśli danych jest mniej niż podana długość, to zwrócone zostaną wszystkie dane z pliku.

Funkcja fread() powoduje przesunięcie wewnętrznego wskaźnika pliku do miejsca, w którym zakończyło się czytanie.

Przykładowo, istnieje plik test.txt o następującej zawartości:

To jest przykładowy plik. Służy do testowania funkcji fread.

A teraz kod PHP:

<? 

    $fp = fopen("test.txt", "r");
    $tekst = fread($fp, 10);

?>
Funkcją fopen() plik został o twarty do odczytu, a następnie odczytanych zostało z niego 10 znaków. Zmienna $tekst będzie więc zawierała “To jest pr”. Przesunięty został wewnętrzny wskaźnik pliku, zatem następne wywołanie linii $tekst = fread($fp, 10) spowoduje, że w tej zmiennej znajdzie się tekst “zykładowy ” – kolejne czytanie zaczęło się od miejsca, w którym zakończyło pracę poprzednie wywołanie tej funkcji.

Aby wczytać cały plik do zmiennej wykorzystaj jeszcze jedną funkcję – filesize(nazwa_pliku). Jak widać, różni się ona od pozostałych funkcji tym, że nie pobiera jako argument wskaźnika do pliku, ale jego nazwę. Wczytanie całej zawartości pliku do zmiennej zrealizujesz w jednej linijce kodu:

<? 

$dane = fread(fopen('nazwa_pliku', 'r'), filesize('nazwa_pliku'));

?>

Funkcja fread() będzie czytać dane bez przerwy – od początku pliku do końca, ignorując znaki końca linii – dla tej funkcji to zwykły znak.

Drugim sposobem czytania pliku jest umieszczenie całej jego zawartości w tablicy. Funkcja file(nazwa_pliku) zwraca tablicę, w której każdy element jest osobnym wierszem z pliku, a nazwa jest podana w argumencie. Przy pomocy tej funkcji jesteś w stanie wczytać całą zawartość pliku do jednego stringa:

<? 

$dane = implode("\n", file('nazwa_pliku'));

?>
Samo wczytanie pliku do tablicy także może być przydatne. Jeśli potraktujesz plik jako bazę danych, w której każdy wiersz to jeden rekord, wczytanie takiego pliku bezpośrednio do tablicy oszczędza wiele pracy przy ręcznym rozbijaniu go na wiersze.

Zapis do plików

Dane do pliku można zapisać przy pomocy funkcji fputs(wskaznik, treść [, długość]). Jak przy większości funkcji operujących na plikach, niezbędne jest podanie wskaźnika pliku, na którym chcesz operować. Zapisać można albo całą zawartość zmiennej podanej jako drugi argument, albo tylko do pewnej długości, którą należy podać jako trzeci, opcjonalny parametr.

Zapis odbywa się w miejscu, na który wskazuje wewnętrzny wskaźnik pliku, nadpisując dane jeśli wskaźnik ten nie znajduje się na końcu pliku. Nie ma żadnej możliwości bezpośredniego zapisania danych na początku lub w środku pliku. Jedyna możliwość to wczytanie pliku do tymczasowej zmiennej, poprawienie tych danych i ponowny zapis pliku. Przykład:

<? // wczytanie starych danych

    // otwarcie pliku do odczytu
    $fp = fopen('plik.txt', 'r');

    //odczytanie danych
    $stareDane = fread($fp, filesize('plik.txt'));

    // zamknięcie pliku
    fclose($fp);

    // stworzenie nowych danych

    $noweDane  = "Oto linijka umieszczona na początku pliku\n";
    $noweDane .= $stareDane;

    // zapisanie nowych danych

    // otwarcie pliku do zapisu
    $fp = fopen('plik.txt', 'w');

    // zapisanie danych
    fputs($fp, $noweDane);

    // zamknięcie pliku
    fclose($fp);

?>

Zapis na końcu pliku jest już prostą czynnością – wystarczy otworzyć plik w trybie “a” i od razu można dodować dane do pliku.

Funkcje informacyjne

Przy skryptach przeznaczonych do obsługi serwera czy na przykład analizujących system plików, niezbędne jest uzyskanie informacji o konkretnym pliku. PHP oferuje cały zestaw funkcji zwracających dane o pliku o podanej ścieżce.

  • fileatime(nazwa_pliku) – zwraca czas ostatniego odczytu pliku; czas ten jest zwracany w postaci timestamp,
  • filemtime(nazwa_pliku) – zwraca czas ostatniej modyfikacji pliku w formacie timestamp,
  • fileowner(nazwa_pliku) – zwraca identyfikator użytkownika, który jest właścicielem pliku,
  • filegroup(nazwa_pliku) – zwraca identyfikator grupy, do której należy plik (tylko Unix),
  • fileperms(nazwa_pliku) – zwraca prawa dostępu do pliku,
  • filesize(nazwa_pliku) – zwraca wielkość pliku w bajtach,
  • filetype($nazwa_pliku) – zwraca typ pliku (tylko UNIX); możliwe typy to “fifo”, “char”, “dir”, “block”, “link”, “file”, “unknown” dla odpowiednio kolejek fifo, urządzeń znakowych, katalogów, urządzeń blokowych, dowiązań, zwykłych plików i nieznanych typów.

Funkcje logiczne (zwracają wartość true lub false)

  • is_dir(nazwa_pliku) – czy plik o podanej ścieżce jest katalogiem,
  • is_executable(nazwa_pliku) – czy plik jest wykonywalny,
  • is_file(nazwa_pliku) – czy plik jest normalnym plikiem,
  • is_link(nazwa_pliku) – czy plik jest dowiązaniem,
  • is_readable(nazwa_pliku) – czy plik można czytać,
  • is_writable(nazwa_pliku) – czy do pliku można pisać,
  • is_uploaded_file($nazwa_pliku) – czy plik został przesłany z formularza.

Kopiowanie

Do kopiowania plików służy funkcja copy(). Pierwszy argument to nazwa pliku źródłowego, a drugi – nazwa pliku lub katalogu docelowego. Funkcja ta zwraca wartość “true” jeśli kopiowanie się powiodło lub “false” w przeciwnym przypadku.

Zawsze dobrze jest sprawdzić, czy kopiowanie pliku się powiodło. Do przenoszenia i zmiany nazwy plików służy jedna funkcja – rename(). Pobiera ona dwa argumenty: nazwę pliku źródłowego oraz nazwę pliku docelowego – jeśli funkcja ma zmienić nazwę; nazwę katalogu jeśli plik ma być przeniesiony, lub ścieżkę wraz z nową nazwą, jeśli plik ma być przeniesiony ze zmianą nazwy.

Przenoszenie i zmiana nazwy

Do przenoszenia i zmiany nazwy plików służy jedna funkcja – rename(). Pobiera ona dwa argumenty: nazwę pliku źródłowego oraz nazwę pliku docelowego – jeśli funkcja ma zmienić nazwę; nazwę katalogu jeśli plik ma być przeniesiony, lub ścieżkę wraz z nową nazwą, jeśli plik ma być przeniesiony ze zmianą nazwy. Kilka przykładów:

<?  

    rename('aaa', 'bbb');      // zmiana nazwy pliku "aaa" na "bbb"
    rename('bbb', 'test/');    // przeniesienie pliku "bbb" do katalogu 
                               // o nazwie "test"
    rename('aaa', '..');       // przeniesienie pliku "aaa" do katalogu 
                               // nadrzędnego
    rename('aaa', 'test/bbb'); // przeniesienie pliku "aaa" do katalogu 
                               // "test" ze zmianą nazwy na "bbb"
?>

Usuwanie

Usuwanie plików jest rzeczą sprawiającą najwięcej trudności początkującym programistom PHP. Dzieje się tak głównie dlatego, że funkcja usuwająca pliki nazywa się unlink(nazwa_pliku), co jest wynikiem tego, że PHP powstało początkowo pod systemy uniksowe. Funkcja ta może nie działać pod systemami Windows – tam najoczywistszym rozwiązaniem jest wywołanie programu del z odpowiednim parametrem.

Do usuwania katalogów służy funkcja rmdir(nazwa).

Tworzenie katalogów

Tworzeniem katalogów zajmuje się funkcja mkdir(nazwa_katalogu, prawa). Drugi argument określa prawa dostępu dla nowego katalogu. W przypadku kont w sieci home.pl, argument ten powinien być zawsze wartością liczbową “0700” (bez cudzysłowów). Funkcja zwraca wartość “true” jeśli katalog został utworzony lub “false” w przeciwnym przypadku.

Przetwarzanie ścieżki

PHP posiada wiele funkcji do analizy i przetwarzania zmiennych tekstowych, które zawierają ścieżkę do pliku. Funkcja basename(path) zwraca nazwę pliku, a dirname(path) wszystko oprócz nazwy pliku. Z kolei funkcja pathinfo(path) zwraca tablicę asocjacyjną zawierającą informację o ścieżce podanej jako parametr – klucz dirname zawiera nazwę katalogu, basename nazwę pliku, a extension – rozszerzenie pliku.

Przykład:

<? 

    $path = "/moja/strona/index.html";

    echo dirname($path);    // wyświetli "/moja/strona"
    echo basename($path);   // wyświetli "index.html"
    $arr = pathinfo($path);
    echo $arr["dirname"];   // wyświetli "/moja/strona"
    echo $arr["basename"];  // wyświetli "index.html"
    echo $arr["extension"]; // wyświetli "html"

?>

Operacje na katalogach

Istnieją dwa mechanizmy przeglądania zawartości katalogów. Pierwszy jest oparty na dwóch funkcjach: opendir(katalog) i readdir(handle). Funkcja opendir() otwiera katalog o podanej nazwie i zwraca uchwyt do niego. Z kolei funkcja readdir() za każdym wywołaniem zwraca nazwę kolejnego pliku/katalogu z otwartego katalogu.

Poniższy przykład wyświetla wszystkie nazwy plików z katalogu:

<? 
   
    if ($dir = @opendir("/tmp")) {
        while($file = readdir($dir)) {
            echo "$file\n";
    }  

    closedir($dir);
}

?>

Drugi sposób oparty jest na mechanizmie pseudo-obiektowym. Oto przykład:

<?$d = dir('/etc');

echo 'Handle: '.$d->handle."
\n";
echo 'Path: '.$d->path."
\n";

while ($entry = $d->read()) {
echo $entry."
\n";
}

$d->close();

?>
Obiekt zwracany przez funkcję dir(katalog) posiada trzy metody: handle() zwraca zwykły uchwyt, który może być używany w funkcji readdir(), metoda path() zwraca string zawierający ścieżkę do katalogu, a metoda read() zwraca kolejne nazwy plików/katalogów, podobnie jak funkcja readdir().

Dla funkcji readdir() i metody read() nie ma różnicy między plikiem lub katalogiem – zwracane są wszystkie nazwy z katalogu. Rozróżnienie między plikiem i katalogiem programista musi zrealizować sam, używając funkcji is_dir().

  • Czy artykuł był pomocny ?
  • Tak   Nie

Tematy powiązane

Szukaj
Generic filters
Tylko dokładne dopasowania
Szukaj w tytułach
Szukaj w treści
Wyświetl posty typu:
lub