PHP :: Редактирование содержимого файла
Редактирование содержимого файла подразумевает осуществление таких операций, как открытие и закрытие файла, чтение и запись, получение текущего значения файлового указателя и его перемещение в соответствии с заданными параметрами, сброс файлового буфера и некоторые другие операции. При этом, используя для редактирования соответствующие функции PHP, нужно иметь также и некоторое представление о понятиях, которые имеют непосредственное отношение к работе с файлами. Приведем краткое описание наиболее важных из них.
- Файловый дескриптор (от англ. file descriptor) – неотрицательное целое число, которое операционная система возвращает при открытии файла (в случае, если это возможно) и с помощью которого выполняются все остальные файловые операции. По завершении операций и закрытии файла дескриптор теряет смысл.
- Файловый указатель – число, указывающее величину смещения относительно нулевого байта в файле. Обычно по этому адресу осуществляется чтение/запись, если конечно вызов операции чтения/записи не предусматривает указание адреса. При выполнении операций чтения/записи файловый указатель смещается на число прочитанных/записанных байт. В результате последовательный вызов операций чтения позволяет прочитать весь файл не обращая внимания на его размер.
- Файловый буфер – специально выделенный участок памяти (буфер), в котором операционная система осуществляет кэширование файловых операций. При закрытии файла буфер сбрасывается.
- Режим доступа – режим устанавливающий разрешения на чтение и запись файла при его открытии.
Прежде, чем приступить к редактированию содержимого файла, его нужно открыть. Делается это при помощи функции fopen(), которой в качестве обязательных аргументов передаются строки с именем открываемого файла и режимом доступа, принимающего одно из следующих значений:
- 'r' – открывает файл только для чтения и помещает указатель в начало файла;
- 'r+' – открывает файл для чтения и записи и помещает указатель в начало файла;
- 'w' – открывает файл только для записи, помещает указатель в начало файла и обрезает файл до нулевой длины; если файл не существует – пытается его создать;
- 'w+' – открывает файл для чтения и записи, помещает указатель в начало файла и обрезает файл до нулевой длины; если файл не существует – пытается его создать;
- 'a' – открывает файл только для записи и помещает указатель в конец файла; если файл не существует – пытается его создать;
- 'a+' – открывает файл для чтения и записи и помещает указатель в конец файла; если файл не существует – пытается его создать;
- 'x' – создаёт и открывает файл только для записи и помещает указатель в начало файла; если файл уже существует, вызов fopen() закончится неудачей, вернёт FALSE и выведет ошибку; если же файл не существует, то функция попытается его создать;
- 'x+' – создаёт и открывает файл для чтения и записи и помещает указатель в начало файла; если файл уже существует, вызов fopen() закончится неудачей, вернёт FALSE и выведет ошибку; если же файл не существует, то функция попытается его создать;
- 'c' – открывает файл только для записи, помещает указатель в начало файла, но сам файл при этом в отличие от режима доступа 'w' не обрезается, а вызов к этой функции не вызывает ошибку; если файл не существует, то он создается;
- 'c+' – открывает файл для чтения и записи, помещает указатель в начало файла, но сам файл при этом в отличие от режима доступа 'w+' не обрезается, а вызов к этой функции не вызывает ошибку; если файл не существует, то он создается.
Поскольку различные операционные системы имеют собственные соглашения по обозначению конца строки, следует быть внимательным при записи данных в текстовый файл, правильно устанавливая символы конца строки в соответствии с операционной системой, под которой работает скрипт: \n для Unix/Linux, \r\n для Windows и \r для Macintosh. Также рекомендуется при использовании данной функции устанавливать флаг трансляции, который может принимать два значения: t, которое предназначено для автоматического перевода \n в \r\n в текстовых файлах в случае работы скрипта под Windows, и b, которое устанавливает бинарный режим обработки файла (например, изображения), не предусматривающий преобразования данных и оперирующий не символами, а байтами. Для задания любого из этих режимов, следует просто дописать соответствующий флаг в строке с режимом доступа, например, 'rt' или же 'wb'. Полагаться на первое значение не стоит, поэтому рекомендуется всегда применять бинарный режим обработки файлов, правильно обрабатывая символы конца перевода строк. Помочь в этом может, например, специальная константа PHP_EOL, которая содержит корректный символ конца строки, используемый на данной платформе.
Рассмотрим использование функции fopen() на примере №1.
<?php //Открываем файл, находящийся в корневой папке сайта, //для чтения в бинарном режиме $handel=fopen('/test_1.txt', 'rb') //Поднимаемся на уровень вверх из папки со скриптом и открываем файл для записи $handel=fopen('../test_2.txt', 'w') //Открываем файл на сервере для чтения и записи в бинарном режиме $handel=fopen('https://html.okpython.net/test_3.txt', 'r+b') ?>
Пример №1. Использование функции fopen()
После того, как файл будет успешно открыт, fopen() вернет дескриптор файла, который будет доступен другим функциям для работы с содержимым файла вплоть до его закрытия при помощи функции fclose(). Пусть, например, у нас имеется обычный текстовый файл test.txt (см. пример №2).
Я текстовый файл.
Пример №2. Содержимое текстового файла test.txt
Рассмотрим на его примере некоторые имеющиеся возможности для чтения файлов (см. пример №3).
<?php echo '-------- fgets() -------- <br><br>'; //Используем ф-цию fopen() и откроем файл в режиме бинарного чтения //(по байтам) $handle=fopen('test_4.txt', 'rb'); //Функция feof() проверяет достигнут ли конец файла и возвращает true, //если указатель файла указывает на конец файла, иначе - false. //В качестве аргумента принимает дискриптор файла, поэтому для //удобства мы его сохранили в переменной //Цикл будет закончен при достижении конца файла while(!feof($handle)){ //fgets() считывает строку из файла, аргументом служит дескриптор файла. //Также посмотрите fgetss(), которая считывает строку, при этом //отбрасывая html-теги //Выведет все три строки файла test.txt echo fgets($handle).'<br>'; } //После завершения работы с файлом не забываем закрыть его fclose($handle); echo '<br><br>'; echo '-------- fgetc() -------- <br><br>'; //Теперь продемонстрируем посимвольное чтение открытого файла //Используем функцию fopen() и откроем файл в режиме бинарного чтения $handle=fopen('test_4.txt', 'rb'); //fgetc() считывает по одному символу и возвращает false при достижении //конца файла. Здесь мы в качестве примера изменили условие, присвоив //переменной дескриптор файла $my_text=''; while($fc=fgetc($handle)){ $my_text.=$fc; //За цикл все символы файла будут занесены в переменную } //Т.к. переносы строк в HTML преобразуются в пробелы, то для вывода в //браузер мы используем nl2br(), которая вставляет '<br>' перед //символами переноса строк //Также выведет все три строки файла test.txt echo nl2br($my_text); //После завершения работы с файлом не забываем закрыть его fclose($handle); echo '<br><br>'; echo '-------- fread() -------- <br><br>'; //Для чтения заданного объема файла в бинарно-безопасном режиме используется //ф-ция fread(), возвращающая прочтенную строку или false в случае ошибки //Используем функцию fopen() и откроем файл в режиме бинарного чтения $handle=fopen('test_4.txt', 'rb'); //Аргументами являются файловый дескриптор и требуемый размер //(мы считываем весь файл) $my_text=fread($handle, filesize('test_4.txt')); //Т.к. переносы строк не работают в HTML, то для правильного вывода в //браузер можно опять использовать nl2br(), которая вставляет '<br>' //перед символами переноса строк //Также выведет все три строки файла test.txt //echo nl2br($my_text); //Но мы в качестве примера используем //str_replace("". PHP_EOL ."", "<br>", $my_text) echo str_replace("". PHP_EOL ."", "<br>", $my_text); //После завершения работы с файлом не забываем закрыть его fclose($handle); echo '<br><br>'; echo '-------- fseek() -------- <br><br>'; //Для смещения файлового указателя в нужную позицию (указывается в байтах) //используется fseek(), которая возвращает 0 в случае успеха и -1 при //возникновении ошибки. Также смотрите ftell(), которая сообщает текущую //позицию чтения/записи файла и rewind(), которая сбрасывает курсор //файлового указателя в начало файла //Используем функцию fopen() и откроем файл в режиме бинарного чтения $handle=fopen('test_4.txt', 'rb'); //Начнем считывать файл с середины, для этого сместим указатель в //середину файла fseek($handle, filesize('test_4.txt')/2); //Поскольку нужно считать половину файла, размер чтения также будет //равен половине $my_text=fread($handle, filesize('test_4.txt')/2); //Выведет лишь часть файла, где первым символом будет 'кракозябра' из-за того, //что указатель попал между байтами, отвечающими за многобайтовый символ echo nl2br($my_text); //После завершения работы с файлом не забываем закрыть его fclose($handle); echo '<br><br>'; echo '-------- file_get_contents() -------- <br><br>'; //Если файл нужно просто прочитать, то это можно сделать за одну операцию //при помощи file_get_contents(), которая считывает содержимое файла в //строку и возвращает ее в случае успеха, иначе - false. При этом не нужно //открывать файл при помощи fopen(). Также см. file(), которая читает //содержимое файла и помещает его в массив //Опять получим 3 строки файла echo nl2br(file_get_contents('test_4.txt')); echo '<br><br>'; ?>
Пример №3. Чтение содержимого файлов
Имеются в PHP и функции для записи данных в файл (см. пример №4). При этом следует помнить, что при открытии файла для записи нужно выбирать соответствующий режим записи. Например, если данные должны быть дописаны в файл, а не перезаписаны, то режим 'w' не подойдет, поскольку в этом случае файловый указатель будет помещен в начало файла, а сам файл будет урезан до нулевой длины.
<?php echo '-------- fwrite() -------- <br><br>'; //Используем функцию fopen() и откроем файл в бинарном режиме записи и чтения $handle=fopen('test_4.txt', 'a+b'); //fwrite() (или же fputs()) - записывает строку указанной длины в файл //Возвращает количество записанных байт или false в случае ошибки //Т.к. в режиме 'a+b' указатель помещается в конец файла, то данные будут не //перезаписаны, а также добавлены в конец файла fwrite($handle, PHP_EOL .'Еще строка текста.'); //Чтобы прочитать измененный файл, вернем указатель в начало файла rewind($handle); //Выведем обновленное содержимое файла на экран echo nl2br(fread($handle, 10000)); //После завершения работы с файлом не забываем закрыть его fclose($handle); echo '<br><br>'; echo '-------- file_put_contents() -------- <br><br>'; //file_put_contents() - записывает строку в файл. При этом открывать файл не //нужно. Записываемые данные, которые могут быть строкой, массивом или //ресурсом, передаются вторым аргументом. По умолчанию файл будет перезаписан, //однако в качестве 3-го аргумента можно передать дополнительный флаг //FILE_APPEND (данные записываются в конец файла). Одновременно можно указать //FILE_USE_INCLUDE_PATH - файл будет дополнительно искаться в подключаемых //директориях, и LOCK_EX - файл будет блокирован на время записи. Функция //возвращает количество записанных байт или false в случае ошибки. В примере //указанная строка будет дописана в конец файла, а сам файл на время записи //будет заблокирован file_put_contents('test_4.txt', PHP_EOL .'Еще строка.', FILE_APPEND|LOCK_EX); //Выведем обновленное содержимое на экран echo nl2br(file_get_contents('test_4.txt')); echo '<br><br>'; echo '-------- flock() -------- <br><br>'; //flock() - блокирует файл, не позволяя другим пользователям читать файл или //записывать данные в него. Для этого в качестве второго аргумента //используются флаги LOCK_SH - разделяемая блокировка (чтение), LOCK_EX - //эксклюзивная блокировка (запись), LOCK_UN - снятие блокировки (разделяемой //или эксклюзивной). Возвращает true в случае успеха, иначе - false //Откроем файл в режиме чтения и записи $handle=fopen('test_4.txt', 'a+b'); //Если файл удачно заблокируется, то начнем перезапись if(flock($handle, LOCK_EX)){ //Функция ftruncate() урезает файл до указанной длинны (см. справочник) ftruncate($handle, 0); //Записываем данные fwrite($handle, PHP_EOL .'Новый текст.'); //Отпираем файл flock($handle, LOCK_UN); }else{ echo "Попробуйте обратиться к файлу позже!"; } //Вернем указатель в начало файла rewind($handle); //Выведем измененное содержимое файла на экран echo nl2br(fread($handle, 10000)); //После завершения работы с файлом не забываем закрыть его fclose($handle); ?>
Пример №4. Запись данных в файл
Быстрый переход к другим страницам
- Операции, не связанные с открытием файла в PHP
- Редактирование содержимого файла в PHP
- Работа с каталогами в PHP
- Вернуться к оглавлению учебника