html.okpython.net
HTML и CSS для начинающих

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 htmlCodes
<?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).

TXT htmlCodes
Я 
текстовый
файл.

Пример №2. Содержимое текстового файла test.txt

Рассмотрим на его примере некоторые имеющиеся возможности для чтения файлов (см. пример №3).

PHP htmlCodes
<?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 htmlCodes
<?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. Запись данных в файл

Быстрый переход к другим страницам