Теоретический материал

Лабораторная работа №14

ФАЙЛЫ в PHP

Цель работы

1. Изучить основы использования файлов в РНР для сохранения и восстановления данных.

2. Применить полученные знания для написания сценариев на PHP.

Задание для подготовки к работе

Изучить лекционный материал и теоретический материал настоящей лабораторной работы.

Порядок выполнения работы

1. Изучить основы использования файлов в РНР.

2. Разработать 3 сценария на языке РНР(3 модуля):

1. для занесения информации приведенной в варианте вашего задания в файл, расположенный в виртуальном каталоге Web-сервера;

2. для просмотра информации занесенной в файл на Web-сервере;

3. для реализации индивидуального задания по предлагаемому вам варианту задания.

3. Выполнить разработанные сценарии.

4. Составить электронный отчет о проделанной работе.

Содержание отчета

1. Титульный лист.

2. Теоретическая часть.

Обязательно указать номер варианта, текст индивидуального задания, тестовые данные, разработать блок-схему для реализации алгоритма решения индивидуального задания.

3. Копии экрана, иллюстрирующие работу сценариев PHP.

4. Коды разработанных сценариев.

Теоретический материал

Работа с файлами. Запись данных в файл реализуется в три шага:

1) Открытие файла. Если файл еще не существует, его потребуется создать.

2) Запись данных в файл.

3) Закрытие файла.

Аналогично, считывание данных из файла также связано с выполнением трех шагов:

1) Открытие файла. Если файл не может быть открыт (например, он не существу­ет), эта ситуация должна быть распознана и следует предусмотреть корректный выход из нее.

2) Считывание данных из файла.

3) Закрытие файла.

При необходимости считывания данных из файла можно выбирать, какая часть файла "должна считываться за один раз". Чуть позже будут подробно рассматриваться все доступные возможности. Пока давайте исследуем шаг открытия файла.

Открытие файла. Для открытия файла в среде РНР используется функция fopen(). При открытии файла необходимо указать режим его использования.

Режимы файлов. Серверная операционная система должна знать, что нужно делать с открываемым файлом. Ей требуется знать, может ли файл быть открыт и обработан другим сцена­рием в то время, когда он является открытым, если владелец сценария имеет право на подобное его использование. Режимы файла предоставляют операционной системе механизм для определения способа обработки запросов на доступ, поступаю­щих от других пользователей или сценариев, а также метод проверки наличия досту­па и прав для работы с конкретным файлом.

При открытии файла следует принять три решения:

1) Файл можно открыть только для чтения, только для записи или для чтения и за­писи.

2) При выполнении записи в файл можно перезаписать любое существующее содер­жимое файла либо же дописать новые данные в конец файла.

3) При попытке выполнения записи в файл в системе, которая различает двоичные и текстовые файлы, может потребоваться указать тип файла.

Функция fopen() поддерживает любые имеющие смысл комбинации этих трех вариантов. Использование функции fopen() для открытия файла. Предположим, что требуется записать заказ клиента в файл. Этот файл можно открыть для записи так:

$fp = fopen("/orders/orders.txt", "w');

Функция fopen ожидает двух или трех входных параметров. Обычно используются два параметра, как показано в приведенной выше строке кода.

Первым параметром должен быть файл, который необходимо открыть. При этом можно указать путь к файлу, как было сделано в приведенной выше строке кода — orders.txt находится в каталоге orders.

Второй параметр функции fopen() — это режим файла, который должен иметь строковый тип. Этот параметр определяет, что необходимо делать с файлом. В данном случае в функцию fopen() передается параметр "w" — это означает открытие файла для записи. Режимы файла перечислены ниже в таблице.

Режим Значение
r Режим чтения — Открытие файла для чтения, начиная с начала файла.
r+ Режим чтения — Открытие файл для чтения и записи, начиная с начала файла.
w Режим записи — Открытие файла для записи, начиная с начала файла. Если файл уже существует, его содержимое удаляется. Если файл не существует, предпринимается попытка его открытия и в результате файл создается.
w+ Режим записи — Открытие файла для записи и чтения, начиная с начала файла. Если файл уже существует, его содержимое удаляется. Если файл не существует, предпринимается попытка его открытия и в результате файл создается.
a Режим добавления — Открытие файла только для добавления (записи), начиная с конца существующего содержимого, если оно имеется. Если файл не существует, предпринимается попытка его открытия и в результате файл создается.
a+ Режим добавления — Открытие файла для добавления (записи) и чтения, начиная с конца существующего содержимого, если оно имеется. Если файл не существует, предпринимается попытка его открытия и в результате файл создается.
b Двоичный режим — Используется в сочетании с одним из остальных режимов. Его указание требуется, если файловая система различает двоичные и текстовые файлы. Операционная система Windows различает эти файлы, а UNIX - нет.

Режим файла, который необходимо использовать в рассматриваемом примере, зависит от того, как будет использоваться система. Параметр "w" позволяет сохранить в файл только один заказ. При приеме каждого нового заказа он будет перезаписывать ранее записанный заказ. Вероятно, это не очень разумно, поэтому лучше указать режим добавления:

$fp = fopen("../../orders/orders.txt", "a");

Третий параметр функции fopen() не является обязательным. Его можно использовать, если файл необходимо искать в пути include_path (определенном в конфигурации РНР). Если это требуется, установите параметр равным 1 и не задавайте имя каталога или путь:

$fp = fopen("orders.txt", "a", 1);

В случае успешного открытия файла функция fopen() возвращает указатель на файл и сохраняет его в переменой, в данном случае $fp. Эта переменная будет использоваться для доступа к файлу, когда потребуется выполнить считывание либо запись в него.

Открытие удаленных файлов через FTP или HTTP. Используя функцию fopen(), можно открывать для чтения или записи не только локальные файлы, но и удаленные с использованием протоколов FTP и HTTP. Если используемое имя файла начинается с ftp://, открывается FTP-соединение с указанным сервером в пассивном режиме и возвращается указатель на начало файла. Если используемое имя файла начинается с http://, открывается HTTP-соединение с указанным сервером и возвращается указатель на ответ от сервера.

Функция fopen() не поддерживает перенаправление HTTP, поэтому необходимо указывать URL-адреса (унифицированный локатор ресурсов), которые ссылаются на каталоги с завершающими символами косой черты. Помните, что имена доменов в URL-адресах не зависят от регистра, однако пути и имена файлов зависят.

Запись в файл. Запись в файл в РНР выполняется сравнительно просто. Для этого можно воспользоваться любой из функций fwrite() (file write — запись в файл) или fputs() (file put string — запись строки в файл); fputs() — это псевдоним функции fwrite(). Функцию fwrite() можно вызвать следующим образом:

fwrite($fp, $outputstring);

Это указывает РНР на необходимость записи строки из переменной $outputstring в файл, указанный $fp. Рассмотрим функцию fwrite() более подробно, прежде чем приступать к исследованию содержимого переменной $outputstring.

Параметры функции fwrite(). В действительности функция fwrite() принимает три параметра, однако третий из них не является обязательным. Прототип fwrite() имеет вид

int fputs(int fp, string str, int [length]);

Третий параметр length представляет собой максимальное количество байтов, которые требуется записать. При передаче этого параметра функция fwrite() будет записывать строку str в файл, указанный параметром fp, пока не встретит конец строки или не запишет length байтов, в зависимости от того, что произойдет раньше.

Закрытие файла. По завершении использования файла его следует закрыть при помощи функции fclose(), как показано ниже:

fclose($fp);

Эта функция возвращает значение true в случае успешного закрытия файла и false, если файл не был закрыт. Ошибка при этом значительно менее вероятна, чем при открытии файла, поэтому в данном случае проверка выполнения функции не выполняется.

Считывание из файла. Уже сейчас клиенты могут отправлять свои заказы через Web, однако если сотрудники компании захотят взглянуть на заказы, им придется открывать файлы самостоятельно. Давайте создадим Web-интерфейс, который позволит служащим компании легко читать файлы. Код этого интерфейса приведен ниже в листинге.

<html>

<head>

<title> Auto Parts - Customer Orders</title></head>

<body>

<hl> Auto Parts</hl> <h2>Customer Orders</h2>

<?

@$fp = fopen("/orders/orders.txt", "r");

if (!$fp) {

echo "<p><strong>No orders pending."

."Please try again later.</strong></p></body></html>";

exit; }

while (!feof($fp)) {

$order= fgets($fp, 100);

echo $order."<br>"; }

fclose($fp);?>

</body>

</html>

В этом сценарии выполняется ранее описанная последовательность действий: открытие файла, считывание из файла, закрытие файла. Давайте подробнее рассмотрим функции, используемые в этом сценарии.

Открытие файла для чтения: fopen(). Как и ранее, мы открываем файл с помощью функции fopen(). На этот раз файл открывается только для чтения, поэтому используется режим файла "r":

$fp = fopen("/orders/orders.txt", "r");

Определение конца файла: feof(). В этом примере используется цикл while для считывания из файла до тех пор, пока не будет достигнут конец файла. Проверка на наличие конца файла осуществляется при помощи функции feof():

while (!feof($fp))

Функция feof() принимает в единственном параметре указатель файла. Она будет возвращать значение true, если указатель файла находится в конце файла. Имя функции легко запомнить, если знать, что feof означает File End Of File (Файл: конец файла).

В данном случае (и вообще при считывании) считывание из файла выполняется до тех пор, пока не будет достигнут EOF.

Построчное считывание: fgets(), fgetss() и fgetcsv(). В рассматриваемом примере для считывания из файла используется функция

fgets(): $order= fgets($fp, 100);

Эта функция используется для считывания из файла по одной строке за один раз. В данном случае считывание будет выполняться до тех пор, пока не встретится символ новой строки (\n), EOF или из файла не будут прочитаны 99 байт. Максимальная длина считываемой строки равна указанной длине минус один байт.

Интересным вариантом функции fgets() является fgetss(), имеющая следующий прототип:

string fgetss (int fp, int length, string [allowable_tags]);

Эта функция во многом подобна функции fgets() за исключением того, что она будет избавляться от любых дескрипторов РНР и HTML, найденных в строке.

Отсутствие ограничений на наличие в файле HTML-кода может привести к нарушению тщательно спланированного форматирования. Отсутствие ограничений на наличие в файле РНР-кода может предоставить злонамеренному пользователю почти полную свободу действий на сервере.

Функция fgetcsv() — еще одна вариация функции fgets(). Она имеет следующий прототип:

array fgetcsv(int fp, int length, string [delimiter]);

Эта функция используется для разделения строк файлов при использовании в качестве разделительного символа табуляции, как предлагалось ранее, или запятой, которая обычно применяется в электронных таблицах и других приложениях. Если требуется восстановить переменные заказа отдельно одна от другой, а не в виде строки текста, следует прибегнуть к функции fgetcsv(). Она вызывается подобно функции fgets(), но ей необходимо передать разделитель, используемый для разделения полей. Например,

$order = fgetcsv($fp, 100, "\t");

получает строку из файла и разбивает ее при каждом обнаружении символа табуляции (\t). Результирующие данные помещаются в массив (в этом примере — в $order).

Параметр length должен быть больше длины самой длинной строки считываемого файла, выраженной в символах.

Считывание всего файла: readfile(), fpassthru(), file(). Вместо считывания по одной строке из файла за один проход можно считывать весь файл. Существуют три различных способа.

Первый заключается в использовании функции readfile(). Весь ранее созданный сценарий можно заменить одной строкой:

readfile("/orders/orders.txt");

Функция readfile() открывает файл, повторяет его содержимое в стандартном выводе (окне браузера), а затем закрывает файл. Прототип этой функции имеет вид

int readfile (string имя_файла, int [use_include_path]);

Необязательный второй параметр указывает, должен ли РНР искать файл в пути use_include_path, и действует так же, как в функции fopen(). Функция возвращает общее количество байтов, считанных из файла.

Во-вторых, можно использовать функцию fpassthru(). Вначале необходимо открыть файл с помощью функции fopen(). Затем указатель файла можно передать в функцию fpassthru(), которая загрузит содержимое файла, начиная с позиции, заданной указателем, в стандартный вывод. По завершении этого процесса функция закрывает файл.

Ранее приведенный сценарий можно заменить функцией fpassthru() следующим образом:

$fp = fopen("/orders/orders.txt", "r");

Функция fpassthru() возвращает значение true, если считывание было выполнено Успешно, и false — в противном случае.

Третья возможность считывания всего файла — использование функции file(). Эта Функция идентична функции readfile() за исключением того, что вместо повторения файла в стандартном выводе она преобразует его в массив. Ее вызов выглядит так:

$filearray = file($fp);

Эта строка приведет к считыванию всего файла в массив, названный $filearray. каждая строка файла сохраняется в отдельном элементе массива.

Считывание символа: fgetc(). Еще одна возможность обработки файлов — считывание из файла по одному символу. Это выполняется с помощью функции fgetc(). В качестве своего единственного параметра она принимает указатель файла и возвращает следующий символ файла Цикл while в первоначальном сценарии можно заменить циклом, в котором используется функция fgetc():

while (!feof($fp))

{

$char = fgetc($fp); if (!feof($fp))

echo ($char=="\n"? "<br>": $char);

}

Используя функцию fgetc(), этот код считывает из файла по одному символу за раз и сохраняет его в переменной $char, пока не будет достигнут конец файла. Затем выполняется небольшая дополнительная обработка с целью замещения текстовых символов конца строки \n HTML-разделителями строк <bг>. Это делается лишь для приведения в порядок форматирования. Поскольку без этого кода браузеры не распознают новые строки, весь файл был бы выведен в виде единой строки. (Попытайтесь сделать это и посмотрите, что получится.)

Побочный эффект использования функции fgetc() вместо функции fgets() заключается в том, что она будет возвращать символ EOF, в то время как fgets() не делает этого. После считывания символа приходится снова выполнять проверку с помощью функции feof(), поскольку символ EOF не должен отображаться в окне браузера.

В общем случае считывание файла символ за символом не находит особого применения, если только по какой-либо причине не требуется посимвольная обработка файла.

Считывание строк произвольной длины: fread(). Последний способ считывания из файла, который мы рассмотрим — использование функции fread() для считывания из файла произвольного количества байтов. Эта функция имеет следующий прототип:

string fread(int fp, int length);

Функция считывает length байтов или все байты до конца файла, в зависимости от того, что произойдет раньше.

Проверка существования файла: file_exists(). Если необходимо проверить файл на предмет существования без его открытия, можно воспользоваться функцией file_exists(), как показано в следующем примере:

if (file_exists("/orders/orders.txt"))

echo "Файл orders имеется"; else

echo " Файла orders нет";

Выяснение размера файла: filesize(). Размер файла можно проверить с помощью функции filesize(). Она возвращает размер файла, выраженный в байтах:

echo filesize("/orders/orders.txt");

Эта функция может применяться в сочетании с функцией fread() для одновременного считывания всего файла (или определенной его части). Весь первоначальный сценарий можно заменить следующим кодом:

$fp = fopen("/orders/orders.txt", "r");

echo fread($fp, filesize("/orders/orders.txt"));

fclose($fp);

Удаление файла unlink(). Если файл заказов необходимо удалить, это выполняется с помощью функции unlink(). (Нет ни одной функции с именем delete.) Например:

unlink("/orders/orders.txt");

Эта функция возвращает значение false, если файл не может быть удален. Это будет происходить при недостаточном уровне прав доступа к файлу или если файл не существует.

Перемещение внутри файла: rewind(), fseek() и ftell(). Выяснять позицию указателя файла внутри файла и изменять ее можно с помощью функций rewind(), fseek() и ftell().

Функция rewind() переустанавливает указатель файла на начало файла. Функция ftell() сообщает в байтах позицию указателя относительно начала файла. В нижнюю часть первоначального сценария (перед командой fclose()) можно добавить следующие строки:

echo "Final position of the file pointer is ".(ftell($fp));

rewind($fp);

echo ""<br>After rewind, the position is ". (ftell ($fp));

echo "<br>";

Функция fseek() может использоваться для установки указателя файла в некоторую точку внутри файла. Ее прототип имеет вид

int fseek(int fp, int offset);

В результате вызова функции fseek() указатель файла fp устанавливается в точку файла, имеющую смещение offset байтов относительно начала файла. Вызов функции rewind() эквивалентен вызову функции fseek() со смещением, равным нолю. Например, функцию fseek() можно использовать для нахождения средней записи в файле или для выполнения бинарного поиска.

Блокирование файлов. Представьте себе ситуацию, когда два клиента одновременно пытаются заказать товар. (Эта ситуация возникает не столь уж редко, особенно когда Web-сайт начинает обрабатывать значительные информационные потоки.) Что произойдет, если один клиент вызовет функцию fopen() и начнет запись, а затем второй клиент также вызовет функцию fopen() и тоже попытается выполнить запись? Ответ на этот вопрос зависит от используемой операционной системы, но часто точно ответить на них невозможно.

Во избежание подобных проблем используется блокирование файлов. В РНР блокирование реализуется с помощью функции flock(). Эта функция должна вызываться после открытия файла, но перед считыванием данных из файла или их записью в файл.

Прототип функции flock() выглядит так:

bool flock(int fp, int operation);

В функцию необходимо передать указатель на открытый файл и число, представляющее вид требуемой блокировки. Функция возвращает значение true, если блокировка была успешно выполнена, и false — в противном случае.

Возможные значения параметра operation перечислены ниже в таблице.

Значение параметра operation Описание
  Блокировка чтения. Это означает, что файл может использоваться совместно с другими читающими приложениями.
  Блокировка записи. Это монопольный режим. Файл не доступен для совместного использования.
  Снятие существующей блокировки.
+4 Добавление 4 к текущему значению параметра operation предотвращает другие попытки блокирования во время выполнения текущего блокирования.

Если решено использовать функцию f lock(), ее следует включить во все сценарии, в которых используется данный файл; в противном случае ее применение лишено смысла.

Для использования блокирования в рассматриваемом ниже примере необходимо изменить следующим образом:

$fp = fopen("/orders/orders.txt", "a", 1);

flock($fp, 2); // блокирование файла для записи

fwrite($fp, $outputstring);

flock($fp, 3); // снятие блокировки записи

fclose($fp);//Следует добавить блокировки в файл vieworders.php:

$fp = fopen("/orders/orders.txt", "r");

flock($fp, 1); // блокирование файла для чтения

flock($fp, 3); // снятие блокировки записи

fclose($fp);


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: