Wejście - Wyjście
Przyjrzymy się, jak PHP zarządza danymi wejściowymi i wyjściowymi. Zbadamy, w jaki sposób możemy czytać z systemu plików lub sieci lub z niego zapisywać.
Pliki
Istnieją dwie główne grupy funkcji do obsługi plików: te, które działają z zasobami plików i te, które działają z nazwą pliku. Pamiętaj, że zasób jest rodzajem zmiennej, której nie można przechowywać bezpośrednio w PHP. Zasób pliku to uchwyt pliku systemu operacyjnego. Wszystkie funkcje zajmujące się zasobami plików zaczynają się od jednej litery f, a następnie mają czasownik opisujący ich funkcję. Na przykład fopen() otwiera zasób pliku. Funkcje, które działają z nazwą łańcucha pliku, zaczynają się od pliku słowa, a po nim następuje czasownik opisujący to, co robią. Na przykład file_get_contents() pobiera ciąg nazwy pliku i zwraca zawartość tego pliku.
Otwieranie plików
Funkcja fopen() służy do otwierania plików. Zwraca zmienną zasobu, która jest uchwytem do pliku. Musisz przekazać dwa parametry do fopen():
• Nazwa pliku w systemie plików
• Tryb pliku, w którym chcesz go otworzyć
Tryby plików
Pliki można otwierać w różnych trybach. Tryby plików opisują sposób interakcji z plikiem. Tryby plików dotyczą uprawnień do plików systemu operacyjnego. Na przykład, jeśli użytkownik PHP ma dostęp tylko do odczytu pliku, próba otwarcia go w trybie zapisu zostanie odrzucona przez system operacyjny. Jeśli spróbujemy z mniejszymi uprawnieniami (np. Tylko do odczytu), system operacyjny utworzy dla nas uchwyt pliku. Przekazujemy dwie informacje o tym, jak zamierzamy użyć pliku, gdy określimy tryb:
• Czy czytamy, piszemy, czy jedno i drugie
• Czy chcemy umieścić wskaźnik pliku na początku, czy koniec pliku Wskaźnik pliku jest jak kursor iteratora. Przechowuje pozycję pliku, która zostanie zwrócona przy następnym odczycie. Poniższa tabela zawiera zestawienie popularnych trybów plików.
Tryb : Odczyt/Zapis : Wskaźnik : Zachowanie
r : R : Start
r+ : RW : Start
w : W : Start : Obcina istniejący plik lub tworzy nowy plik, jeśli jest nie istnieje
w+ : RW : Start
a : W : Start : Tworzy nowy plik, jeśli nie istnieje i zachowuje bieżący plik, jeśli taki jest
a+ : RW : Start
x : W : Nie dotyczy : Próbuje utworzyć nowy plik do zapisu; zwraca FALSE, jeśli plik już istnieje i generuje E_WARNING
x+ : RW
c : W : Start : Próbuje utworzyć plik, jeśli nie istnieje; jeśli to istnieje, umieszcza kursor na początku pliku
c+ : RW
Zauważysz, że dodanie symbolu + do trybu pliku skutkuje wskazaniem, że chcesz również wykonać odwrotność trybu domyślnego. Kiedy nadpisujemy plik, jeśli dodamy symbol +, oznacza to, że chcemy również odczytać plik. Zachowanie pozostaje jednak takie samo, dlatego pominąłem je w tabeli, aby ułatwić czytanie. Podczas nadpisywania pliku za pomocą trybów w PHP PHP skróci plik do zera bajtów. Jest to przydatne, jeśli chcesz mieć plik, który jest zastępowany nowymi danymi. Tryby x zwrócą FALSE i wygenerują ostrzeżenie, jeśli plik już istnieje. Jest to przydatne, jeśli chcesz uniknąć zastępowania danych, które chcesz zachować. Tryb c utworzy plik, jeśli istnieje lub otworzy istniejący plik. Wskaźnik zostanie ustawiony na początku pliku dla istniejących plików.
Flagi trybu pliku
Istnieją dwie flagi, które można określić, dodając je na końcu ciągu trybu. Domyślna flaga jest zdefiniowana przez twój SAPI i wersję PHP, której używasz, więc dla celów kompatybilności powinieneś je określić. Możesz określić flagę b, aby określić, że pracujesz z plikami binarnymi. Oznacza to, że żadne znaki nie zostaną przetłumaczone. Jest to konieczne, gdy pracujesz z obrazami lub inne pliki binarne. Na serwerze Windows możesz określić flagę t, aby przetłumaczyć \ n na \ r \ n.
Wskazówka : Aby zachować przenośność kodu, należy użyć flagi b i upewnić się, że kod zawiera prawidłowe zakończenia linii.
Odczytywanie plików
Możesz czytać z zasobu pliku za pomocą funkcji fread().
< ?php
$handle = fopen('info.txt', 'r');
while (!feof($handle)) {
echo fread($handle,1024);
}
W tym przykładzie używamy funkcji pliku feof (), która zwraca wartość PRAWDA, gdy wskaźnik pliku znajduje się na końcu pliku, w przeciwnym razie NIEPRAWIDŁOWY. Używanie go w pętli while powoduje kontynuowanie pętli, aż dojdziemy do końca pliku. Funkcja fread () przyjmuje dwa parametry. Pierwszy to zmienna przechowująca zasób pliku, a drugi to liczba bajtów do odczytania. Jeśli dojdzie do końca pliku, fread () przestanie czytać. Oto cztery dodatkowe funkcje PHP, które ułatwiają czytanie plików:
Funkcja : Używana do
fgetcsv() : Odczytaj wiersz ze wskaźnika pliku i parsuj dla pól CSV
file_get_contents() : Weź nazwę pliku i odczytaj wyniki w pliku
readfile() : Przeczytaj nazwę pliku i zapisz zawartość do plik bufora wyjściowego
file() : Przeczytaj cały plik do tablicy
Zapisywanie do plików
Zapis do pliku odbywa się za pomocą binarnie bezpiecznej funkcji fwrite (). fputs () jest aliasem tej funkcji. Funkcja fwrite () przyjmuje dwa parametry - zasób pliku do zapisu i ciąg do zapisu do pliku. Istnieje funkcja zapisu dla funkcji fgetcsv (), a mianowicie fputcsv (), która formatuje tablicę jako CSV i zapisuje linię do pliku. Oprócz parametrów zasobu pliku i tablicy, do zdefiniowania formatu CSV potrzebne są parametry opcjonalne. Jeśli chcesz zapisać sformatowane ciągi do pliku, powinieneś użyć fprintf (), która działa jak polecenie printf (). Jeśli chcesz zrzucić zawartość pliku do podłączonego klienta, możesz użyć fpassthru (). Ta funkcja uruchomi się w bieżącej pozycji pliku i zapisze resztę pliku w buforze wyjściowym. Wreszcie, istnieje wygodna funkcja szybkiego zapisywania ciągu do pliku. Funkcja file_put_contents () nie wymaga podania zasobu pliku, a jedynie nazwę pliku i ciąg znaków, które chcesz zapisać. Oto prosty przykład użycia niektórych z tych funkcji:
< ?php
$filename = 'test.csv';
$dataString = '1,2,3,4,5';
file_put_contents($filename, $dataString);
$handle = fopen($filename, 'r');
$myData = fgetcsv($handle);
echo gettype($myData); // array
echo count($myData); // 5
W tym przykładzie używamy funkcji skrótu file_put_contents (), aby wyprowadzić ciąg znaków do pliku. Nie musimy mieć dostępnego zasobu pliku, ponieważ file_put_contents () obsługuje to za nas. Po napisaniu ciągu otwieram zasób pliku, aby go odczytać i używam fgetcsv () do odczytu z pliku. Ciąg był prawidłową listą CSV i tak $myData zawiera tablicę pięciu elementów.
Funkcje systemu plików
PHP ma obszerną listę funkcji, które łączą cię z systemem plików. W tym rozdziale zajmiemy się kilkoma z nich, ale jak to często robię, odsyłam cię do podręcznika PHP w celu uzyskania wyczerpującej listy.
Katalogi
Ta grupa funkcji umożliwia przechodzenie, tworzenie i usuwanie katalogów.
Funkcja : Zastosowanie
chdir() : Zmienia bieżący katalog roboczy PHP.
chroot() : Zmienia katalog główny uruchomionego procesu na określony katalog i ustawia katalog roboczy PHP na /.
rmdir() :Usuwa katalog.
readdir() : Zwraca nazwę następnego wpisu w uchwycie katalogu przekazanym jako parametr. Wpisy są zwracane w kolejności, w jakiej są przechowywane przez system plików.
scandir () Czyta katalog określony przez parametr string i zwraca listę zawartych w nim plików i katalogów
Różnica między scandir() a readdir() jest parametrem, który przyjmują. Tam, gdzie readdir () używa uchwytu katalogu, scandir() akceptuje nazwę katalogu jako ciąg znaków.
Uwaga : Jest to prawdopodobnie mylące, ponieważ wydaje się, że konwencja nazewnictwa funkcji plików (f * versus file *) nie ma zastosowania do katalogów.
Informacje o pliku
Wspomnieliśmy o tych funkcjach w części poświęconej bezpieczeństwu, ale istnieją inne przypadki użycia, w których musisz uzyskać informacje o pliku. PHP udostępnia funkcję finfo_open(), która zwraca nową instancję zasobu fileinfo. Dostarczasz mu dwa parametry - predefiniowaną stałą opcji i lokalizację ciągu do pliku magicznej bazy danych. Plik magicznej bazy danych jest formatem używanym do opisywania typów plików i jest także używany przez standardowe polecenie Uniksa, file. Jeśli nie podasz ścieżki do magicznej bazy danych, PHP użyje tej, z którą jest dołączona. Gdy PHP już wie, jak identyfikować pliki, możesz użyć funkcji finfo_file() w celu uzyskania informacji o pliku. Wymaga co najmniej dwóch parametrów - właśnie utworzonego zasobu fileinfo i nazwy ciągu pliku, który chcesz sprawdzić. Oto przykład z podręcznika PHP:
< ?php
$finfo = finfo_open(FILEINFO_MIME_TYPE);
foreach (glob("*") as $filename) {
echo finfo_file($finfo, $filename) . "\n";
}
finfo_close($finfo);
Obie funkcje mają styl obiektowy, jak w tym przykładzie z podręcznika PHP:
< ?php
// finfo will return the mime type
$finfo = new finfo(FILEINFO_MIME, "/usr/share/misc/magic");
/* get mime-type for a specific file */
$filename = "/usr/local/something.txt";
echo $finfo->file($filename);
Zarządzanie plikami
Możesz używać PHP do zarządzania plikami. Niektóre z typowych funkcji są wymienione w tej tabeli.
Funkcja : Cel
copy : Kopiuje plik.
unlink : Usuwa plik.
rename : Zmienia nazwę pliku. Możesz użyć tego do przeniesienia pliku między katalogami.
chmod : Ustawia uprawnienia do plików.
chgrp : Zmienia grupę pliku.
chown : Zmienia właściciela pliku (tylko superuser).
umask : Zmienia bieżący umask.
Określanie typu obiektu systemu plików
Dobrą praktyką programistyczną jest sprawdzanie, czy istnieją pliki i katalogi oraz czy masz odpowiednie uprawnienia do korzystania z nich w zamierzony sposób. PHP udostępnia funkcje, które zwracają wartości logiczne, jeśli obiekt pasujący do ciągu przekazywanego jako parametr spełnia test. Te funkcje pobierają parametr ciągu, który jest nazwą pliku lub katalogu. W poniższej tabeli kontrola dotyczy znalezionego obiektu pasującego do nazwy podanej w parametrze.
Funkcja : Sprawdza
is_dir : Jest katalogiem
is_file : To plik
is_readable : Jest plikiem lub katalogiem i można go odczytać
is_writeable : To plik lub katalog i można do niego zapisać
is_executable Jest plikiem lub katalogiem i można go wykonać
is_link : Jest dowiązaniem symbolicznym
is_uploaded_file :Został przesłany przez żądanie POST
Wszystkie funkcje zwrócą FALSE, jeśli nie znaleziono obiektu systemu plików, który pasowałby do nazwy podanej w parametrze.
Magiczne stałe pliku
PHP ma kilka magicznych stałych, których możesz użyć w stosunku do aktualnie wykonywanego pliku.
Stała: Odnosi się
__LINE__ : Linia aktualnie wykonywanego pliku
__FILE__ : Pełna ścieżka i nazwa pliku
__FUNCTION__ : Nazwa bieżącej funkcji
__CLASS__ : Nazwa klasy w zakresie
__METHOD__ : Nazwa wykonywanej metody
Te stałe są bardzo przydatne podczas pisania dzienników debugowania. Na przykład zwykle zaczynam wszystkie moje wiadomości w dzienniku od znacznika __METHOD__, aby od razu było jasne, która klasa i metoda, w której generowany jest komunikat dziennika.
Strumienie
Strumienie w PHP to sposób na uogólnienie operacji na plikach, sieci, kompresji danych i innych operacji, które dzielą zestaw typowych funkcji i zastosowań. Strumień jest prawie jak przenośnik taśmowy rzeczy, które przychodzą do ciebie jedna po drugiej. W PHP możesz również przeskakiwać wzdłuż taśmy przenośnika i szukać pozycji zamiast czekać, aż do ciebie dotrze. Strumienie są przywoływane w formacie, który można rozpoznać:
schemat: // cel
Na przykład http://www.php.net określa schemat http i cel jako adres URL strony internetowej PHP.
Strumieniowe owijanie
Opakowania są obiektami kodu, które tłumaczą strumień na określone kodowanie lub protokół. Podręcznik PHP3 zawiera listę opakowań, które są zaimplementowane w języku, a funkcja stream_wrapper_register() pozwala ci zdefiniować własne.
Protokół : Wykorzystanie
file: // - Dostęp do lokalnego systemu plików
http: // - Uzyskiwanie dostępu do adresów URL HTTP
ftp: // - Uzyskiwanie dostępu do adresów URL FTP
php: // - Uzyskiwanie dostępu do różnych strumieni we / wy
compress.zlib: // - Strumienie kompresji
data: // - Data (RFC 2397)
glob: // - Znajdź ścieżki pasujące do wzorca
phar: // - archiwum PHP
ssh2: // - Secure Shell 2
rar: // - RAR
ogg: // - strumienie audio
expect: // - Przetwarzaj strumienie interakcji
Strumienie PHP, do których można uzyskać dostęp, to stdin, stdout, stderr, input, output, fd, memory, temp i filter. Pamiętaj, że w celu poprawy czytelności pominąłem protokół dla wszystkich tych strumieni. Kiedy ich używasz, wszystkie powinny być poprzedzone protokołem php: //, na przykład stdin to php: // stdin. Jako przykład czytania strumienia przyjrzyjmy się, jak odczytać treść żądania PUT. W pewnym momencie swojej kariery będziesz kodować interfejs API REST i będziesz musiał przeczytać i przeanalizować treść żądań PUT wysyłanych przez klientów na Twój serwer. Nie ma superglobalności dla tego typu żądania, podobnie jak dla GET i POST, więc jak to się robi? Odpowiedź znajduje się w strumieniu wejściowym php: //!
< ? php
// odczytuje treść PUT
$ input = file_get_contents ('php: // input');
// analizuje dane wejściowe w tablicy
parse_str ($ input, $ params);
print_r ($ params);
Filtry
Filtry strumieniowe można stosować do strumieni i przeprowadzać operacje transformacji danych opuszczając strumień.
Filtr : Funkcja
string.rot13 Koduje dane za pomocą ROT13
string.toupper : Konwertuje ciąg na wielkie litery
string.tolower : Konwertuje ciąg na małe litery
string.strip_tags : Usuwa tagi XML z łańcucha
convert. * : Konwertuje dane na przykład zgodnie z algorytmem
mcrypt. * : Zapewnia szyfrowanie symetryczne przy użyciu libmcrypt
mdecrypt. * : Filtr deszyfrujący używający libmcrypt
zlib. * : Używa biblioteki ZLIB do kompresji i dekompresji danych
Te filtry są dołączone do strumienia za pomocą funkcji stream_filter_append (). Możesz zastosować filtr niezależnie do kierunków odczytu i zapisu strumienia.
< ?php
stream_filter_append($handle, 'string.rot13');
$handle = fopen("files.php", 'a+');
while (!feof($handle)) {
echo fread($handle,1024);
}
Możesz podać trzeci parametr do stream_filter_append (), aby dołączyć go do odczytu lub zapisu strumienia. Ten parametr jest jedną z predefiniowanych stałych STREAM_FILTER_READ, STREAM_FILTER_WRITE lub STREAM_FILTER_ALL. Domyślnie filtr jest dołączany do odczytu i zapisu. Ten przykład wyświetli coś takiego:
< ?cuc
$ unaqyr = sbcra ("svyrf.cuc", 'n +');
fgernz_svygre_nccraq ($ unaqyr, 'fgevat.ebg13');
juvyr (! srbs ($ unaqyr)) {
rpub sernq ($ unaqyr, 1024);
}
Strumieniowe konteksty
br>
Konteksty strumienia są opakowaniami dla zestawu opcji, które mogą modyfikować zachowanie strumienia. Kontekst tworzy się za pomocą funkcji stream_context_create(). Przekazujesz jej dwa opcjonalne parametry, z których oba są tablicami asocjacyjnymi. Pierwszy parametr to opcje, a drugi to tablica parametrów kontekstu. Każdy typ strumienia ma swój własny zestaw opcji kontekstowych. Podręcznik PHP ma ich wyczerpującą listę. Jedynym dostępnym obecnie parametrem jest wywołanie, które zostanie wywołane, gdy zdarzenie wystąpi w strumieniu. Wszystkie zdarzenia są predefiniowanymi stałymi STREAM_NOTIFY_ *. Prototyp funkcji wywołania zwrotnego znajduje się w podręczniku PHP wraz z przykładem zdarzeń powiadomień dla strumienia HTTP. Na przykład, jeśli pobierasz plik, możesz skonfigurować funkcję wywołania zwrotnego, aby reagowała na zdarzenie STREAM_NOTIFY_FILE_SIZE_IS i przerwała pobieranie, jeśli jest ono zbyt duże. Ten przykład uniemożliwia nam pobranie strony głównej www.example.com, jeśli jest ona większa niż kilobajt.
< ?php
function callback($notification_code,
$severity,
$message,
$message_code,
$bytes_transferred,
$bytes_max)
{
if ($notification_code == STREAM_NOTIFY_FILE_SIZE_IS) {
if ($bytes_max > 1024) {
die("Download too big!");
}
}
}
$context = stream_context_create();
stream_context_set_params($context, ["notification" => "callback"]);
$handle = fopen('http://www.example.com', 'r', false, $context);
fpassthru($handle);
Możesz zmienić opcje i parametry za pomocą funkcji stream_context_set_params(), a stream_context_get_params() zwróci bieżące parametry strumienia.
QUIZ
P1: Załóżmy, że użytkownik serwera WWW jest właścicielem pliku data.csv i zawiera ciąg "Hello World" przed uruchomieniem tego skryptu. Jakie będą wyniki tego kodu?
< ?php
file_put_contents('data.csv', '1,2,3,4,5');
$handle = fopen('data.csv', 'c+');
$data = fgetcsv($handle, 2);
var_dump($data[1]);
---------------------------------
string(0) ""
string(1) ","
string(1) "1"
string(1) "2"
To spowoduje błąd
P2: Jakie będą dane wyjściowe tego kodu?
< ?php
file_put_contents('test.csv', '1,2,3,4,5');
$handle = fopen('test.csv', 'c');
fputcsv($handle, ['6', '7', '8']);
fclose($handle);
echo file_get_contents('test.csv');
---------------------------------
To stworzy błąd
1,2,3,4,5,6,7,8
6,7,8,1,2,3,4,5
6,7,8
1,2,3,4,5
6,7,8,1,2,3,4,5
1,2,3,4,5
6,7,8
P3: Jeśli piszesz interfejs REST i potrzebujesz odczytać parametry wysłane w żądaniu PUT, jak możesz to zrobić?
---------------------------------
Odwołaj się do superglobala $ _REQUEST
Odwołaj się do superglobala $ _POST
Oczytaj strumień php: // input
Odczytaj strumień http: // input
P4: Chcę zapisać wpisy dziennika do pliku, gdy mój program PHP działa. Nie chcę stracić starych wpisów w dzienniku i potrzebuję, aby moje wpisy były w odpowiedniej kolejności dat, a najnowsze wpisy następowały po starszych wpisach. W jakim trybie pliku powinienem otworzyć plik?
---------------------------------
r
a
x
c
P5: Załóżmy, że plik, który odzyskuję, jest prawidłowym obrazem w formacie GIF i że korzystam z PHP w Linuksie. Jakie będą wyniki tego kodu?
< ?php
// To jest poprawny obrazek GIF
$url = ' https://goo.gl/QycgqH';
file_put_contents('earth.gif', file_get_contents($url));
if (!rename('earth.gif', 'earth.jpeg')) {
throw new RuntimeException('Could not rename the file.');
}
$finfo = new finfo();
echo $finfo->file('earth.jpeg') . PHP_EOL;
---------------------------------
To powoduje błąd
Dane obrazu GIF, wersja 89a, 400 x 400
Dane obrazu JPEG, 400 x 400
obraz / gif
image / jpeg
Nie można zmienić nazwy pliku
Żadne z powyższych
ODPOWIEDZI
• string(0) ""
• 6,7,8 ; 1,2,3,4,5
• Oczytaj strumień php: // input
• a
• Dane obrazu GIF, wersja 89a, 400 x 400