Лабораторная работа №6 - Работа с файловой системой

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

Режимы работы с файлами

Можно выделить два режима работы с файлом:

  1. текстовый
  2. бинарный

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

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

В PHP в обоих случаях при чтении и записи используется строковый тип данных, так как типа «массив байт» здесь просто нет. Но отличие все же есть, и заключается оно в трансляции символа переноса строки.

В системах семейства Unix для перевода строки используется символ «\n», в то время как в Windows – последовательность из двух символов «\r\n». Трансляция символа перевода строки нужна для того, чтобы программист не зависел от операционной системы. Таким образом, можно считать, что для новой строки следует всегда использовать «\n», интерпретатор сам откорректирует чтение и запись.

Функции работы с файлами

int fopen(string $filename, string $mode, bool $use_include_path=false)

Открывает файл с именем $filename в режиме $mode и возвращает дескриптор открытого файла. Если операция "провалилась", то, как это принято, fopen() возвращает false. Необязательный параметр $use_include_path говорит PHP о том, что, если задано относительное имя файла, его следует искать также и в списке путей, используемом инструкциями include и require. Обычно этот параметр не используют. Параметр $mode может принимать следующие значения:

mode Описание
'r' Файл открывается только для чтения. Если файла не существует, вызов регистрирует ошибку. После удачного открытия указатель файла устанавливается на его первый байт, т. е. на начало.
'r+' Файл открывается одновременно на чтение и запись. Указатель текущей позиции устанавливается на его первый байт. Как и для режима r, если файла не существует, возвращается false.
'w' Открывает файл только для записи; помещает указатель в начало файла и обрезает файл до нулевой длины. Если файл не существует - пробует его создать.
'w+' Аналогичен r+, но если файла изначально не существовало, создает его. После этого с файлом можно работать как в режиме чтения, так и записи. Если файл существовал до момента вызова, его содержимое удаляется.
'a' Открывает существующий файл в режиме записи, и при этом сдвигает указатель текущей позиции за последний байт файла. Этот режим полезен, если требуется что-то дописать в конец уже имеющегося файла. Вызов неуспешен в случае отсутствия файла.
'a+' Открывает файл в режиме чтения и записи, указатель файла устанавливается на конец файла, при этом содержимое файла не уничтожается. Отличается от a тем, что если файла изначально не существовало, то он создается. Этот режим полезен, если вам нужно что-то дописать в файл (например, в журнал), но вы не знаете, создан ли уже такой файл

В конце любой из строк r, w, a, r+, w+ и a+ может находиться еще один необязательный символ — b или t. Если указан b (или не указан вообще никакой), то файл открывается в режиме бинарного чтения/записи. Если же это t, то для файла устанавливается режим трансляции символа перевода строки, т. е. он воспринимается как текстовый.

int tmpfile()

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

int fclose(int $fp)

Закрывает файл. Возвращает истину при успехе, false при «провале». PHP автоматически закрывает открытые файлы при завершении выполнения сценария. Однако хорошим тоном считается самостоятельно закрывать дескриптор сразу после завершения работы с файлом.

string fread(int $f, int $numbytes)

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

int fwrite(int $f, string $st)

Записывает в файл $f все содержимое строки $st. Эта функция составляет пару для fread(), действуя «в обратном направлении». При работе с текстовыми файлами (то есть когда указан символ t в режиме открытия файла) все «\n» автоматически преобразуются в тот разделитель строк, который принят в вашей операционной системе.

string fgets(int $f, int $length)

Читает из файла одну строку, заканчивающуюся символом новой строки «\n». Этот символ также считывается и включается в результат. Если строка в файле занимает больше $length-1 байтов, то возвращаются только ее $length-1 символов. Функция полезна, если вы открыли файл и хотите "пройтись" по всем его строкам. Однако даже в этом случае лучше (и быстрее) будет воспользоваться функцией File().

int fputs(int $f, string $st)

Эта функция — синоним fwrite(). Отличие в том, что пару fread/fwrite принято использовать при работе с бинарными файлами, а пару fputs/fgets – с текстовыми (когда запись и чтение осуществляются построчно).

int feof(int $f)

Возвращает true, если достигнут конец файла.

int fseek(int $f, in $offset, int $whence = SEEK_SET)

Устанавливает указатель файла на байт со смещением $offset (от начала файла, от его конца или от текущей позиции, в зависимости от параметра $whence). Параметр $whence, как уже упоминалось, задает, с какого места от считывается смещение $offset. В PHP для этого существуют три константы, равные, соответственно, 0, 1 и 2:

  • SEEK_SET — отсчитывает позицию относительно начала файла
  • SEEK_CUR — отсчитывает позицию относительно текущей позиции
  • SEEK_END — отсчитывает позицию относительно конца файла

В случае использования последних двух констант параметр $offset вполне может быть отрицательным (а при применении SEEK_END он будет отрицательным наверняка). Как это ни странно, но в случае успешного завершения эта функция возвращает 0, а в случае неудачи -1.

int ftell(int $f)

Возвращает положение указателя файла.

int filesize(string $filename)

Более простой способ определения размера файла.

bool file_exists(string $filename)

Возвращает true, если файл с именем $filename существует.

bool is_file(string $filename)

Возвращает true, если $filename — обычный файл.

bool is_dir(string $filename)

Возвращает true, если $filename — каталог.

string basename(string $path)

Выделяет основное имя файла из пути $path.

string dirname(string $path)

Возвращает имя каталога, выделенное из пути $path.

bool copy(string $src, string $dst)

Копирует файл с именем $src в файл с именем $dst. При этом, если файл $dst на момент вызова существовал, осуществляется его перезапись. Функция возвращает true, если копирование прошло успешно, а в случае провала — false.

bool rename(string $oldname, string $newname)

Переименовывает (или перемещает, что одно и то же) файл с именем $oldname в файл с именем $newname. Если файл $newname уже существует, регистрируется ошибка, и функция возвращает false.

bool unlink(string $filename)

Удаляет файл с именем $filename. В случае неудачи возвращает false, иначе — true.

array file(string $filename)

Считывает файл с именем $filename целиком и возвращает массив, каждый элемент которого соответствует строке в прочитанном файле. Функция работает очень быстро — гораздо быстрее, чем если бы мы использовали fopen() и читали файл по одной строке. Неудобство этой функции состоит в том, что символы конца строки не вырезаются из строк файла, а также не транслируются, как это делается для текстовых файлов. Так что, каждый элемент массива иногда имеет смысл преобразовать с помощью функции rtrim().

Пример работы с файлом

Пример 1.

Задание: создать журнал посещения сайта.

Реализация:

Главная страница:

Мы открываем файл режимом «a+», что означает следующее:

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

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

Далее мы записываем в файл три строки.

  • Дата и время
  • IP-адрес
  • Откуда пришел (будет пустым, если прямой заход на сайт, т.е. адрес был набран вручную)

Обратите внимание, что для перехода на новую строку используется последовательность «\n». Ее следует писать в двойных кавычках, тогда она заменится на спецсимвол переноса строки. Если же ‘\n’ написать в апострофах, то это будет просто символ «\», за которым следует символ «n». Наконец, когда работа с файлом завершена, его следует закрыть. Для этого служит функция fclose().

Лабораторная работа №6 - Работа с файловой системой - student2.ru

Страница журнала посещений:

Лабораторная работа №6 - Работа с файловой системой - student2.ru

Лабораторная работа №6 - Работа с файловой системой - student2.ru

Необходимо создать две статичные странички – Сайт1 и Сайт 2 с ссылкой на главную страницу для отслеживания посещаемости.

Загрузка файла на сервер. Пример.

Задание: Реализовать загрузку файла на сервер.

Реализация:

Для того, чтобы загрузить файл на сервер, надо создать html-форму. Для того, чтобы с помощью этой формы можно было загружать файлы, она должна содержать атрибут enctype в теге form со значением multipart/form-data, а также элемент input типа file.

Лабораторная работа №6 - Работа с файловой системой - student2.ru

Лабораторная работа №6 - Работа с файловой системой - student2.ru

Вся информация о загруженном на сервер файле содержится в глобальном массиве $_FILES.

Массив $_FILES всегда имеет следующие элементы:

· $_FILES['myfile']['name'] - имя, которое имел файл на машине клиента.

· $_FILES['myfile']['type'] - mime-тип отправленного файла, если браузер предоставил эту информацию.

· $_FILES['myfile']['size'] - размер загруженного файла в байтах.

· $_FILES['myfile']['tmp_name'] - временное имя файла, под которым он был сохранен на сервере.

· $_FILES['myfile']['error'] - код ошибки, появившейся при загрузке.

Здесь 'myfile' - это имя элемента формы, с помощью которого была произведена загрузка файла на сервер. То есть оно может быть другим, если элемент формы назвать иначе. Но вот другие ключи ( name, type и т. д.) остаются неизменными для любой формы.

Ошибок при загрузке в PHP выделяют пять типов и соответственно $_FILES['myfile']['error'] может иметь пять значений:

  • 0 - ошибки не произошло, файл загружен успешно
  • 1 - загружаемый файл превышает размер, установленный директивой upload_max_filesize в файле настроек php.ini
  • 2 - загружаемый файл превышает размер, установленный элементом MAX_FILE_SIZE формы html
  • 3 - файл был загружен частично
  • 4 - файл загружен не был

По умолчанию загруженные файлы сохраняются во временной директории сервера, если другая директория не указана с помощью опции upload_tmp_dir в файле настроек php.ini. Переместить загруженный файл в нужную директорию можно с помощью функции move_uploaded_file().

Функция move_uploaded_file() имеет следующий синтаксис:

bool move_uploaded_file (временное_имя_файла, место_назначения )

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

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

Обработчик:

Лабораторная работа №6 - Работа с файловой системой - student2.ru

Функции для работы с каталогами

bool mkdir(string $name, int $perms)

Создает каталог с именем $name и правами доступа $perms. Права доступа для каталогов указываются точно так же, как и для файлов. Чаще всего значение $perms устанавливают равным 0770 (предваряющий ноль обязателен — он указывает PHP на то, что это — восьмеричная константа, а не десятичное число). Атрибут доступа 0770 означает "доступен для чтения, записи и исполнения для владельца и его группы". В случае успеха функция возвращает true, иначе — false.

bool rmdir(string $name)

Удаляет каталог с именем $name. В случае успеха возвращает true, иначе — false.

bool chdir(string $path)

Сменяет текущий каталог на указанный. Если такого каталога не существует, возвращает false. Параметр $path может определять и относительный путь, задающийся от текущего каталога.

string getcwd()

Возвращает полный путь к текущему каталогу, начиная от "корня" (/). Если такой путь не может быть отслежен, вызов "проваливается"и возвращает false.

int opendir(string $path)

Открывает каталог $path для дальнейшего считывания из него информации о файлах и подкаталогах и возвращает его идентификатор. Дальнейшие вызовы readdir() с идентификатором в параметрах будут обращены именно к этому каталогу. Функция возвращает false, если произошла ошибка.

string readdir(int $handle)

Считывает очередное имя файла или подкаталога из открытого ранее каталога с идентификатором $handle и возвращает его в виде строки. Вместе с именами подкаталогов и файлов будут также получены два специальных элемента: это «.» (ссылка на текущий каталог) и «..» (ссылка на родительский каталог). В подавляющем большинстве случаев нам нужно их игнорировать. Когда считывать больше нечего функция возвращает false.

void closedir(int $handle)

Закрывает ранее открытый каталог с идентификатором $handle. Не возвращает ничего.

void rewinddir(int $handle)

"Перематывает" внутренний указатель открытого каталога на начало. После этого можно воспользоваться readdir(), чтобы заново начать считывать содержимое каталога.

Задания к лабораторной работе № 6

Задание №6-1

Написать «Гостевую книгу» с сохранением данных переданных пользователем в

текстовый файл. Данные должны храниться в виде строки по принципу: одна строка –

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

Образец:

Лабораторная работа №6 - Работа с файловой системой - student2.ru

Задание №6-2

a) Выведите содержимое текущего каталога.

b) Напишите функцию удаления произвольного каталога и всех его подкаталогов.

Задание №6-3

Создайте галерею фотографий.

Требования:

  1. Возможность загрузки фотографии на сервер (при загрузке должен проверяться тип файла);
  2. Загруженная фотография помещается в новый каталог gallery;
  3. Вывод на экран всех загруженных фотографий;
  4. При загрузке должна автоматически создаваться ее уменьшенная копия (не более 200 пикселей по наибольшей стороне);
  5. Для хранения файлов используется два каталога – один для маленьких изображений, другой – для больших;
  6. Возможность просмотра уменьшенных фотографий (все на одной странице);
  7. Возможность увеличения фотографии при клике по ней (переход на отдельную страницу).

Контрольные вопросы к лабораторной работе №6

  1. Характеризуйте режимы работы с файлами?
  2. Как открыть файл в режиме бинарного чтения/записи?
  3. Как определить размер файла и каталог, в котором он находится?
  4. В чем отличие удаления файла от каталога (с точки зрения алгоритма и применяемых функций)?

Наши рекомендации