Работа с файлами

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

Прежде всего следует упомянуть об именах файлов. Если создается код, который может использоваться на различных установках PHP, то узнать о том, чувствительна система к регистру букв или нет, практически невозможно. Например, имена файлов в Windows и Mac OS X нечувствительны к регистру, а в Linux и UNIX — чувствительны. Поэтому нужно принять за основу то, что система чувствительна к регистру, и придерживаться соглашения о присваивании файлам имен в нижнем регистре.

Файловая система

Проверка существования

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

file_exists()

Функция file_exists() проверяет, существует ли заданный файл. Если файл существует, функция возвращает TRUE, в противном случае возвращается FALSE.

					
	if(file_exists($path)) {
		...
		
	} else {
		echo "File not exists";
		exit(1);
	}
		
					
				

is_file()

Функция is_file() проверяет существование заданного файла и возможность выполнения с ним операций чтения/записи. В сущности, is_file() представляет собой более надежную версию file_exists(), которая проверяет не только факт существования файла, но и то, поддерживает ли он чтение и запись данных. Возвращает TRUE, если файл существует и является обычным файлом, иначе возвращает FALSE.

					
	echo is_file("/");          // FALSE
	echo is_file("text.txt"));  // TRUE
					
				

file_exists
is_file

Создание/Открытие

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

				
	resource fopen ( string $filename , string $mode)
				
			

Функция fopen() присваивает переменной значение. После этого каждой функции обработки файла, которая получает к нему доступ, например fwrite или fclose, в качестве параметра должн быть передан указатель на файл, чтобы идентифицировать обрабатываемый файл. Интересоваться содержимым указателя не стоит, это всего лишь номер, используемый PHP для ссылки на внутреннюю информацию о файле. Данная переменная используется только для передачи другим функциям.

Параметр mode указывает тип доступа, который вы запрашиваете у потока.

Список возможных режимов для fopen()
mode Описание
'r' Открывает файл только для чтения; помещает указатель в начало файла.
'r+' Открывает файл для чтения и записи; помещает указатель в начало файла.
'w' Открывает файл только для записи; помещает указатель в начало файла и обрезает файл до нулевой длины. Если файл не существует - пробует его создать.
'w+' Открывает файл для чтения и записи; помещает указатель в начало файла и обрезает файл до нулевой длины. Если файл не существует - пытается его создать.
'a' Открывает файл только для записи; помещает указатель в конец файла. Если файл не существует - пытается его создать.
'a+' Открывает файл для чтения и записи; помещает указатель в конец файла. Если файл не существует - пытается его создать.
в конце любой из строк может существовать еще один необязательный параметр: b или t. Если указан b, то файл открывается в режиме бинарного чтения/записи. Если же t, то для файла устанавливается режим трансляции перевода строки, т.е. он воспринимается как текстовый.

fclose

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

					
	if(file_exists($path)) {
		$fp = fopen($path, "r");
		...
		
		fclose($fp);
	}
					
				

Оператор управления ошибками

PHP поддерживает один оператор управления ошибками: знак (@). В случае, если он предшествует какому-либо выражению в PHP-коде, любые сообщения об ошибках, генерируемые этим выражением, будут проигнорированы.Оператор управления ошибками

					
	$fp = fopen("nobody.db", "r");  // Warning: fopen(nobody.db): failed to open stream: No such file or directory
	$fp = @fopen("nobody.db", "r"); /*        */
					
				

fopen
touch
fclose

Чтение

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

fgetc

Функция fgetc возвращает строку, содержащую один символ из файла в текущей позиции указателя, или FALSE при достижении конца файла.

					
	$fp = fopen($path, "r");
	
	// EOF - end of file
	while(!feof($fp)) {
		echo fgetc($fp);
	}

	fclose($fp);
					
				

fgets

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

					
	/* СИНТАКСИС */
	//
	// string fgets ( resource $handle [, int $length ] )
	//
	/*************/
				
	if( is_readable($path) ) {
		$fp = fopen($path, "r");
		
		while(!feof($fp)) {
			echo fgets($fp); // fgets
		}

		fclose($fp);
	}
					
				

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

fread

Бинарно-безопасное чтение файла. fread читает до length байт из файлового указателя handle и смещает указатель. Возвращает прочтенную строку или FALSE в случае возникновения ошибки.

					
	/* СИНТАКСИС */
	//
	// string fread ( resource $handle , int $length )
	//
	/**************/
	
	$fp = fopen($path, "r");
	$content = fread($fp, filesize($fp)); // содержимое в одну строку
	fclose($fp);
					
				
На системах, которые различают бинарные и текстовые файлы (к примеру, Windows), файл должен быть открыт с использованием буквы 'b' в параметре mode функции fopen().
					
	$fp = fopen("img.png", "rb");
	$content = fread($fp, filesize($fp)); //
	fclose($fp);
					
				

file_get_contents

Для чтения целиком всего файла без использования указателей файлов можно воспользоваться очень удобной функцией file_get_contents. file_get_contents - читает содержимое файла в строку.

					
	$url = "https://ya.ru";
	echo file_get_contents($url);
					
				

fgets
fgets
fread
file_get_contents
filesize

Запись

is_writable

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

					
	/* СИНТАКСИС */
	//
	// bool is_writable ( string $filename )
	//
	/**************/
	
	if (is_writable($path))	{
		$fp = fopen($path, "w");
		...
		
	} else
		exit(1);
					
				

fwrite

fwrite записывает содержимое string в файловый поток handle(бинарно-безопасная запись в файл).

					
	$fp = fopen($path, "w");
			
	for($i = 0; $i < 10; ++$i) {
		$ms = microtime(TRUE);                              // время с микросекундами
		$str = $i . $sep . md5($ms) . $sep . $ms . PHP_EOL; // правильный конец строки
		fwrite($fp, $str);                                  // длину можно не указывать
		usleep(50000);                                      // замедлене с микросекундами
	}
	
	fclose($fp);
					
				

fprintf

fprintf() - записывает отформатированную строку в поток. Записывает строку, созданную с использованием строки формата format, в поток, дескриптор которого передается в параметре handle. Возвращает длину записанной строки.

					
	/* СИНТАКСИС */
	//
	// int fprintf ( resource $handle , string $format [, mixed $args [, mixed $... ]] )
	//
	/**************/
	
	$fp = fopen($path, "w");
		
	$data = array(
			array(24, "Petrov Pety", "Gorodec"),
			array(31, "Ivanov Ivan", "Zavoljie"),
			array(16, "Sidorov Sidor", "Pravdinsk"),
			array(55, "Mariana Mary", "Chkalovsk"),
	);
	
	foreach($data as $key => $val) {
		fprintf($fp, "%d\t%s\t%s" . PHP_EOL, $val[0], $val[1], $val[2]);
	}
	
	fclose($fp);
					
				
Спецификатор типа
Спецификатор Преобразование
% символ процента. Аргумент не используется.
b аргумент трактуется как целое и выводится в виде двоичного числа.
c аргумент трактуется как целое и выводится в виде символа с соответствующим кодом ASCII.
d аргумент трактуется как целое и выводится в виде десятичного числа со знаком.
e аргумент трактуется как число в научной нотации (например, 1.2e+2). Описатель точности указывает на количество знаков после запятой, начиная с версии PHP 5.2.1. В более ранних версиях он обозначал количество значащих цифр (на один знак меньше).
f аргумент трактуется как число с плавающей точкой и также выводится в зависимости от локали.
o аргумент трактуется как целое и выводится в виде восьмеричного числа.
s аргумент трактуется как строка.
u аргумент трактуется как целое и выводится в виде десятичного числа без знака.
x аргумент трактуется как целое и выводится в виде шестнадцатеричного числа (в нижнем регистре).
Данные спецификаторы типов поддерживаю так же и следующие функции: sprintf, printf, fprintf, fscanf, sscanf

Настройка представления данных

Можно указать не только тип преобразования, но и точность отображаемого результата. Например, суммы в валюте отображаются, как правило, с точностью до двух цифр. Но после вычисления значение может иметь более высокую точность (например, если разделить 123.42 на 12, то получится 10.285). Чтобы обеспечить правильное внутреннее хранение таких значений, но при этом организовать их отображение с точностью только до двух цифр, можно между символом % и спецификатором преобразования вставить строку .2.

					
	$sig_i = -1232244;
	$usig_i = 2432535;
	$fl = M_EULER;     // Постоянная Эйлера
	$str = "Hello? user zamt";
	
	printf("<br>%u    %b    %.4f    %.5s<br>", $sig_i, $usig_i, $fl, $str); // 4293735052 1001010001111000010111 Hello
					
				

Математические константы

Другие операции

Существует ряд полезных системных функций, которые могут выполняться в сценариях PHP.

copy

Копирование файла. Копирует файл source в файл с именем dest.

						
	/* СИНТАКСИС */
	//
	// bool copy ( string $source , string $dest [, resource $context ] )
	//
	/**************/
	
	copy("db.txt", "db.txt.backup");	
						
					
Если целевой файл уже существует, то он будет перезаписан.

rename

Переименовывает файл или директорию. Пытается переименовать oldname в newname, перенося файл между директориями, если необходимо. Если newname существует, то он будет перезаписан. В случае если переименовывается директория и newname уже существует, будет выведено предупреждение.

						
	/* СИНТАКСИС */
	//
	// bool rename ( string $oldname , string $newname [, resource $context ] )
	//
	/**************/
	
	rename("db.txt.backup", "restore.txt");      // переименование
	rename("restore.txt", "backup/restore.txt"); // перемещение
						
					

Удаление

unlink()- удаляет файл. Возвращает TRUE в случае успешного завершения или FALSE в случае возникновения ошибки.

						
	/* СИНТАКСИС */
	//
	// bool unlink ( string $filename [, resource $context ] )
	//
	/**************/
	
	unlink("backup/restore.txt");
						
					

copy
rename
unlink
mkdir
rmdir

fseek

fseek устанавливает смещение в файловом указателе.

						
	int fseek ( resource $handle , int $offset [, int $whence = SEEK_SET ] )
						
			

Устанавливает смещение в файле, на который ссылается handle. Новое смещение, измеряемое в байтах от начала файла, получается путём прибавления параметра offset к позиции, указанной в параметре whence

Режим установки указателя
Значение Описание
SEEK_SET Устанавливает смещение в offset байт.
SEEK_CUR Устанавливает смещение в текущее плюс offset.
SEEK_END Устанавливает смещение в размер файла плюс offset. (Чтобы перейти к смещению перед концом файла, вы должны передать отрицательное значение в параметр offset.)

Если whence не указан, по умолчанию он устанавливается в SEEK_SET.

В случае успеха возвращает 0; в противном сучае возвращает -1. Обратите внимание, что переход к смещению за концом файла не считается ошибкой.

Не может использоваться на файловых указателях, возвращённых функцией fopen(), если они используют форматы "http://" или "ftp://". fseek() также возвращает неопределённый результат для потоков "дописать в конец" (открытых с флагом "a").