< Лабораторная работа № 5. Работа с файлами.


Лабораторная работа № 5.
Работа с файлами.

Цель работы: Изучить приемы работы с файлами в PHP.

Базовые сведения:

Создание файла Функция fopen

Вообще говоря, в PHP не существует функции, предназначенной именно для создания файлов . Большинство функций работают с уже существующими файлами в файловой системе сервера. Есть несколько функций, которые позволяют создавать временные файлы, или, что то же самое, файлы с уникальным для текущей директории именем. А вот для того, чтобы создать самый обычный файл, нужно воспользоваться функцией, которая открывает локальный или удаленный файл. Называется эта функция fopen().

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

resource fopen ( имя_файла, тип_доступа
    [, use_include_path])

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

Параметр имя_файла должен быть строкой, содержащей правильное локальное имя файла или URL-адрес файла в сети. Если имя файла начинается с указания протокола доступа (например, http://... или ftp://...), то интерпретатор считает это имя адресом URL и ищет обработчик указанного в URL протокола. Если обработчик найден, то PHP проверяет, разрешено ли работать с объектами URL как с обычными файлами (директива allow_url_fopen ). Если allow_url_fopen=off, то функция fopen вызывает ошибку и генерируется предупреждение. Если имя файла не начинается с протокола, то считается, что указано имя локального файла. Чтобы открыть локальный файл, нужно, чтобы PHP имел соответствующие права доступа к этому файлу.

Параметр use_include_path, установленный в значение 1 или TRUE, заставляет интерпретатор искать указанный в fopen() файл в include_path. Напомним, что include_path – это директива из файла настроек PHP, задающая список директорий, в которых могут находиться файлы для включения. Кроме функции fopen() она используется функциями include() и require().

Параметр тип_доступа может принимать одно из следующих значений


Table: Значения принимаемые параметром тип доступа
Тип доступа Описание
r Открывает файл только для чтения; устанавливает указатель позиции в файле на начало файла.
r+ Открывает файл для чтения и записи; устанавливает указатель файла на его начало.
w Открывает файл только для записи; устанавливает указатель файла на его начало и усекает файл до нулевой длины. Если файл не существует, то пытается создать его.
w+ Открывает файл для записи и для чтения; устанавливает указатель файла на его начало и усекает файл до нулевой длины. Если файл не существует, то пытается создать его. a Открывает файл только для записи; устанавливает указатель файла в его конец. Если файл не существует, то пытается создать его.
a+ Открывает файл для записи и для чтения; устанавливает указатель файла в его конец. Если файл не существует, то пытается создать его. x Создает и открывает файл только для записи; помещает указатель файла на его начало. Если файл уже существует, то fopen() возвращает false и генерируется предупреждение. Если файл не существует, то делается попытка создать его. Этот тип доступа поддерживается начиная с версии PHP 4.3.2 и работает только с локальными файлами.
x+ Создает и открывает файл для записи и для чтения; помещает указатель файла на его начало. Если файл уже существует, то fopen() возвращает false и генерируется предупреждение. Если файл не существует, то делается попытка создать его. Этот тип доступа поддерживается, начиная с версии PHP 4.3.2, и работает только с локальными файлами.

Итак, чтобы создать файл, нужно открыть несуществующий файл на запись.

<?php
$h = fopen(“my_file.html”,”w”);
/* открывает на запись файл
my_file.html, если он существует, или создает пустой файл с таким
именем, если его еще нет */
$h = fopen(“dir/another_file.txt”,”w+”); /* открывает на запись и
чтение или создает файл another_file.txt в директории dir */
$h = fopen(“http://www.server.ru/dir/file.php”,”r”);
/* открывает на чтение файл, находящийся по указанному адресу*/
?>

Создавая файл, нужно учитывать, под какой операционной системой вы работаете, и под какой ОС предположительно этот файл будет читаться. Дело в том, что разные операционные системы по-разному отмечают конец строки. В Unix-подобных ОС конец строки обозначается \n, в системах типа Windows – \r\n. Windows предлагает специальный флаг t для перевода символов конца строки систем типа Unix в свои символы конца строки. В противоположность этому существует флаг b, используемый чаще всего для бинарных файлов, благодаря которому такой трансляции не происходит. Использовать эти флаги можно, просто дописав их после последнего символа выбранного типа доступа к файлу . Например, открывая файл на чтение, вместо r следует использовать rt, чтобы перекодировать все символы конца строки в \r\n. Если не использовать флаг b при открытии бинарных файлов, то могут появляться ошибки, связанные с изменением содержимого файла. Из соображений переносимости программы на различные платформы рекомендуется всегда использовать флаг b при открытии файлов с помощью fopen().

Если открыть или создать файл с помощью fopen не удается PHP генерирует предупреждение, а функция fopen возвращает как результат своей работы значение false. Такого рода предупреждения можно «подавить» (запретить) с помощью символа @ .

Например, такая команда не выведет предупреждения, даже если открыть файл не удалось:

$h = @fopen(“dir/another_file.txt”,”w+”);

Таким образом, функция fopen() позволяет создать только лишь пустой файл и сделать его доступным для записи.

Закрытие соединения с файлом

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

Эта функция возвращает TRUE, если соединение успешно закрыто, и FALSE – в противном случае. Параметр этой функции должен указывать на файл, успешно открытый, например, с помощью функции fopen().

<?php $h = fopen("my_file.html","w"); fclose($h); ?>
Конечно, если не закрывать соединение с файлом, никаких ошибок выполнения скрипта не произойдет. Но в целом для сервера это может иметь серьезные последствия. Например, хакер может воспользоваться открытым соединением и записать в файл вирус, не говоря уже о лишней трате ресурсов сервера. Так что советуем всегда закрывать соединение с файлом после выполнения необходимых действий.

Запись данных в файл Функция fwrite

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

int fwrite ( указатель на файл, строка [, длина])

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

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

Пусть в нашей рабочей директории нет файла my_file.html. Создадим его и запишем в него строку текста:

<?php $h = fopen("my_file.html","w");
$text = "Этот текст запишем в файл.";
if (fwrite($h,$text))
  echo "Запись прошла успешно";
else
  echo "Произошла ошибка при записи данных";
fclose($h);
?>

В результате работы этого скрипта в браузере мы увидим сообщение о том, что запись прошла успешно, а в файле my_file.html появится строка “Этот текст запишем в файл.”. Если бы этот файл существовал до того, как мы выполнили этот скрипт, все находящиеся в нем данные были бы удалены.

Если же мы напишем такой скрипт:

<?php $h = fopen("my_file.html","a");
$add_text = "Добавим текст в файл.";
if(fwrite($h,$add_text,7))
  echo "Добавление текста прошло
    успешно<br>";
else
  echo "Произошла ошибка при
   добавлении данных<br>";
fclose($h); ?>

то к строке, уже существующей в файле my_file.html, добавится еще семь символов из строки, содержащейся в переменной $add_text, т.е. слово «Добавим»

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

Чтение данных из файла Если мы хотим прочитать данные из существующего файла, одной функции fopen(), как и в случае с записью данных, недостаточно. Она лишь возвращает указатель на открытый файл, но не считывает ни одной строки из этого файла. Поэтому для того, чтобы прочитать данные из файла, нужно воспользоваться одной из специальных функций: file, readfile, file_get_contents, fread, fgets и т.п.

Функция fread

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

string fread (указатель на файл, длина)

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

В результате работы функция fread() возвращает строку со считанной из файла информацией.

В этой функции параметр длина – обязательный. Следовательно, если мы хотим считать весь файл в строку, нужно знать его длину. PHP может самостоятельно вычислить длину указанного файла. Для этого нужно воспользоваться функцией filesize(имя файла). В случае ошибки эта функция вернет false. К сожалению, ее можно использовать только для получения размера локальных файлов.

Прочитаем содержимое файла my_file.html

<?php
$h = fopen("my_file.html","r+");
// отрываем файл на запись и чтение
$content = fread($h,filesize(“my_file.html”));
// считываем содержимое файла в строку
fclose($h);
// закрываем соединение с файлом
echo $content;
// выводим содержимое файла
// на экран браузера
?>

Для того чтобы считать содержимое бинарного файла, например изображения, в таких системах, как Windows, рекомендуется открывать файл с помощью флага rb или ему подобных, содержащих символ b в конце.

Функция filesize() кэширует результаты своей работы. Если изменить содержимое файла my_file.html и снова запустить приведенный выше скрипт, то результат его работы не изменится. Более того, если запустить скрипт, считывающий данные из этого файла с помощью другой функции (например, fgetss), то результат может оказаться таким, как если бы файл не изменился. Чтобы этого избежать, нужно очистить статический кэш, добавив в код программы команду clearstatcache();

Функция fgets

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

string fgets ( указатель на файл [, длина])

В результате работы функция fgets() возвращает строку длиной (длина–1) байт из файла, на который указывает указатель на файл. Чтение заканчивается, если прочитано (длина–1) символов и встретился символ перевода строки или конец файла. Напомним, что в PHP один символ – это один байт. Если длина считываемой строки не указана (данная возможность появилась начиная с PHP 4.2.0), то считывается 1 Кбайт (1024 байт) текста или, что то же самое, 1024 символа. Начиная с версии PHP 4.3, если параметр длина не задан, считывается строка целиком. В случае ошибки функция fgets() возвращает false. Для версий PHP начиная с 4.3 эта функция безопасна для двоичных файлов.

<?php
$h = fopen("my_file.html","r+");
$content = fgets($h,2);
// считает первый символ из
// первой строки файла my_file.html
fclose($h);
echo $content;
?>

Обе функции, fread() и fgets(), прекращают считывание данных из файла, если встречают конец файла. В PHP есть специальная функция, проверяющая, смотрит ли указатель позиции файла на конец файла. Это булева функция feof(), в качестве параметра которой передается указатель на соединение с файлом.

Например, вот так можно считать все строки файла my_file.html:

<?php
$h = fopen("my_file.html","r");
while (!feof ($h)) {
    $content = fgets($h);
    echo $content,"<br>";
}
fclose($h); ?>

Функция fgetss

Существует разновидность функции fgets() – функция fgetss(). Она тоже позволяет считывать строку из указанного файла, но при этом удаляет из него все встретившиеся html-теги, за исключением, быть может, некоторых. Синтаксис fgetss() такой:

string fgetss(указатель на файл,длина [, допустимые теги])

Обратите внимание, что здесь аргумент длина обязательный.

Пусть у нас имеется файл my_file.html следующего содержания:

<h1>Без труда не вынешь и рыбку из пруда.</h1>
<b>Тише едешь – дальше будешь</b>
У семи нянек<i> дитя без глазу</i>.
\begin{verbatim}
Выведем на
экран все строки файла \verb"my_file.html", удалив из них все теги, кроме
\verb"<b>" и \verb"<i>":

\begin{verbatim}
<?php
$h = fopen("my_file.html","r");
while (!feof ($h)) {
    $content = fgetss($h,1024,'<b><i>');
   echo $content,"<br>";}
fclose($h);
?>

 В результате работы этого скрипта получим:

\textbf{Тише едешь – дальше будешь}

Без труда не вынешь и рыбку из пруда.

У семи нянек дитя без глазу.

\textbf{Функция fgetc}

Естественно, если можно считывать информацию из
файла построчно, то можно считывать ее и посимвольно. Для этого
предназначена функция \verb"fgetc()". Синтаксис у
нее следующий:
\begin{verbatim}
string fgetc ( указатель на файл )

Эта функция возвращает символ из файла, на который ссылается указатель на файл, и значение, вычисляемое как FALSE, если встречен конец строки.

Вот так, например, можно считать файл по одному символу:

<?php
$h = fopen("my_file.html","r");
while (!feof ($h)) {
    $content = fgetc($h);
    echo $content,"<br>";
}
fclose($h);
?>

На самом деле для того чтобы прочитать содержимое файла, открывать соединение с ним посредством функции fopen() совсем не обязательно. В PHP есть функции, которые позволяют делать это, используя лишь имя файла. Это функции readfile( ), file( ) и file_get_contents( ).

Функция readfile

Синтаксис:

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

Функция readfile() считывает файл, имя которого передано ей в качестве параметра имя_файла, и выводит его содержимое на экран. Если дополнительный аргумент use_include_path имеет значение TRUE, то поиск файла с заданным именем производится и по директориям, входящим в include_path.

В программу эта функция возвращает число считанных байтов (символов) файла, а в случае ошибки – FALSE. Сообщения об ошибке в этой функции можно подавить оператором @ .

Следующий скрипт выведет на экран содержимое файла my_file1.html и размер этого файла, если он существует. В противном случае выведется наше сообщение об ошибке – строка "Error in readfile".

<?php
$n = @readfile ("my_file1.html");
/* выводит на экран содержимое файла и записывает его размер в переменную $n */
if (!$n) echo "Error in readfile";
/* если функция readfile() выполнилась с ошибкой,
то $n=false и выводим сообщение об ошибке*/
else
echo $n;
  // если ошибки не было, то выводим число
  // считанных символов
?>

С помощью функции readfile() можно читать содержимое удаленных файлов, указывая их URL-адрес в качестве имени файла, если эта опция не отключена в настройках сервера.

Сразу же выводить содержимое файла на экран не всегда удобно. Порой нужно записать информацию из файла в переменную, чтобы в дальнейшем произвести с ней какие-либо действия. Для этого можно использовать функцию file() или file_get_contents().

Функция file

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

array file ( имя_файла [, use_include_path])

Эта функция возвращает массив, каждый элемент данного массива является строкой в файле, информацию из которого мы считываем (его имя задано аргументом имя_файла). Символ новой строки тоже включается в каждый из элементов массива. В случае ошибки функция file(), как и все уже рассмотренные, возвращает false. Дополнительный аргумент use_include_path опять же определяет, искать или нет данный файл в директориях include_path. Открывать удаленные файлы с помощью этой функции тоже можно, если не запрещено сервером. Начиная с PHP 4.3 работа с бинарными файлами посредством этой функции стала безопасной.

Например, у нас имеется файл my_file.html следующего содержания:

 <h1>Без труда не вынешь и рыбку из пруда.</h1>
 <b>Тише едешь – дальше будешь</b>

Прочитаем его содержимое с помощью функции file():

<?php
$arr = file ("my_file.html");
foreach($arr as $i => $a)
echo $i,": ", htmlspecialchars($a), "<br>";
?>
В результате на экран будет выведено следующее сообщение:
0: <h1>Без труда не вынешь
    и рыбку из пруда.</h1>
1: <b>Тише едешь – дальше будешь</b>

Функция file_get_contents

В версиях PHP начиная с 4.3 появилась возможность считывать содержимое файла в строку. Делается это с помощью функции file_get_contents(). Как и две предыдущие функции, в качестве параметров она принимает значение имени файла и, возможно, указание искать его в директориях include_path.

string file_get_contents (имя_файла [, use_include_path])

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

Задание на лабораторную работу

  1. Реализуйте приведенные выше примеры.
  2. Найдите в справочной документации информацию о функциях работы с каталогами в PHP.
  3. Напишите скрипт, создающий файл с кодом текущей страницы.
  4. Элементы массива заданы в файле. Произвести чтение из файла и вывод элементов массива.
  5. Даны три разных файла с одинаковым количеством строк. Написать скрипт, формирующий страницу с содержимым этих файлов в виде $ s1_i <=> s2_i <=> s3_i$, где $ sj_i$ - i-я строка j-го файла.
  6. Даны два файла. Сформировать страницу, содержащую нумерованный список, первый элемент которого - все одинаковые строки файлов, второй элемент которого - строки первого файла, не входящие во второй, третий элемент которого - символы второго файла, входящие в первый.


< <