Работа с файлами
Работа с файлами - важный инструмент PHP.
Включение внешних файлов
В каждый PHP-документ можно включить файл с помощью инструкции include(). Её аргумент: путь к файлу. Этой инструкцией удобно пользоваться при наличии одинаковых кусков кода во многих PHP-программах. Содержимое включаемого файла обрабатывается как простой HTML-текст. Для того, чтобы содержимое этого файла обрабатывалось как PHP-программа, нужно обрамлять его открывающим и закрывающим тегами PHP.
Пример 1
<html>
<head>
<title>Использование include()</title>
</head>
<body>
<?php
include("top.php");
echo "<H2>...Основная часть...</H2>";
?>
</body>
</html>
Включаемый файл top.php с PHP-программой:
echo "<H1 align=center>...Общее приветствие...</H1>"
В данном случае результат будет тем же, если включаемый файл top.php содержит только строку HTML-текста:
<H1 align=center>...Общее приветствие...</H1>
Включаемые файлы могут возвращать значения подобно функциям. Использование оператора return прерывает выполнение этого файла так же, как и функции.
Пример 2
<html>
<head>
<title>Использование инструкции include(), возвращающей значение</title>
</head>
<body>
<?php
$res = include("top.php");
echo "<H2>Включаемый файл вернул $res</H2>";
?>
</body>
</html>
Включаемый файл top.php с PHP-программой:
<?php
$a = 7 * 8;
return $a;
?>
Инструкцию include() можно использовать внутри цикла. В цикле include() выполняется при каждой итерации. Это можно использовать для включения нескольких файлов. Например:
for ($i=1; $i<=5; $i++)
include("incfile{$i}.htm");
Определение имени включаемого файла и его загрузка производятся повторно при
каждом вызове
Оператор include() также можно включать в тело условного оператора.
Несмотря на сходство по внешнему виду с функцией, include() функцией не является, а представляет собой специальную конструкцию языка.
Для указания что файл нужно подключать только один раз используется оператор include_once()
Анализ файлов
PHP содержит множество функций, дающих информацию о файлах. Наиболее употребимыми являются:
- file_exists() - определяет существование файла. Например:
if ( !file_exists( "aaa.php" ) ) echo "Внимание! Файл aaa.php не найден!";
- is_file() - определяет, является ли исследуемый объект файлом.
Например:
if ( is_file( "bbb.txt" ) ) echo "Можете не сомневаться, bbb.txt - это файл";
- is_dir() - определяет, является ли исследуемый объект каталогом.
Например:
if ( is_dir( "/tmp" ) ) echo "Действительно, /tmp - это каталог";
- is_readable() - определяет, доступен ли файл для чтения.
Например:
if ( is_readable( "db.dbf" ) ) echo "db.dbf можно читать";
- is_writable() - определяет, доступен ли файл для записи.
Например:
if ( is_writable( "db.dbf" ) ) echo "В db.dbf писать можно";
- filesize() - определяет размер файла в байтах.
- filemtime() - определяет дату и время последнего изменения файла.
- fileatime() - определяет дату и время последнего обращения к файлу.
Время возвращается в формате Unix, т.е. представляет собой количество секунд, прошедших после 1 января 1970 г. В примере 2 это число преобразуется в понятный для человека формат с помощью функции date( ).
Пример 3
<html>
<head>
<title>Информация о файле</title>
</head>
<body>
<?php
$file = "top.php";
infoFile ( $file );
function infoFile ( $f )
{
if ( !file_exists( $f ) )
{
echo "$f не найден!";
return;
}
echo "$f - ".( is_file( $f ) ? "" : "не " )."файл<br>";
echo "$f - ".( is_dir( $f ) ? "" : "не " )."каталог<br>";
echo "$f ".( is_readable( $f ) ? "" : "не " )."доступен для чтения<br>";
echo "$f ".( is_writable( $f ) ? "" : "не " )."доступен для записи<br>";
echo "размер $f в байтах - ".( filesize( $f ) )."<br>";
echo "последнее изменение $f - ".( date( "d M Y H:i", filemtime( $f ) ) )."<br>";
echo "последнее обращение к $f - ".( date( "d M Y H:i", fileatime( $f ) ) )."<br>";
}
?>
</body>
</html>
Внимание! С удаленными файлами эти функции не работают. Их можно применять только к локальной файловой системе.
Управление файлами
PHP содержит множество функций управления файлами. Наиболее употребимыми являются:
- touch() - создает пустой файл с заданным именем. Если такой
файл уже существует, то функция изменит дату модификации. Например:
touch( "ex1.txt" );
- copy() - копирует файл.
Для копирования файлов в php применяется функция copy ($source, $result). Ей нужно передать лишь два
параметра
- источник $source и имя файла-копии - $result. Стоит отметить, что следует указывать полные адреса к
файлам.
Пример применения функции copy:
<?php if (copy('Z:/home/site/www/file.txt', 'Z:/home/site/www/file2.txt')) { echo "Копирование успешно выполнено"; } else { echo "Ошибка при копировании"; } ?>
- unlink() - удаляет заданный файл. Например:
<?php if (unlink('filename.txt')) { echo "Файл удален"; } else { echo "Ошибка при удалении файла"; } ?>
- fopen( ) - открывает локальный или удаленный файл и возвращает
указатель на него. Указатель используется во всех операциях с содержимым файла.
Аргументы: имя файла и режим открытия.
r чтение. Указатель файла устанавливается на его начало r+ чтение и запись. Указатель файла устанавливается на его начало w запись. Указатель файла устанавливается на его начало. Все старое содержимое файла теряется. Если файл с указанным именем не существует, функция пытается его создать w+ чтение и запись. Указатель файла устанавливается на его начало. Все старое содержимое файла теряется. Если файл с указанным именем не существует, функция пытается его создать a запись. Указатель файла устанавливается на его конец. Если файл с указанным именем не существует, функция пытается его создать a+ чтение и запись. Указатель файла устанавливается на его конец. Если файл с указанным именем не существует, функция пытается его создать Например:
$fp = fopen( "http://www.php.net/", "r" ); // для чтения $fp = fopen( "ex1.txt", "w" ); // для записи $fp = fopen( "ex2.txt", "a" ); // для добавления в конец
Если открыть файл не удалось, то можно прервать выполнение программы. Например:
$fp = fopen( "ex1.txt", "w" ) or die ( "Не удалось открыть файл" );
- fclose() - закрывает файл. Аргумент: указатель файла,
полученный ранее от функции fopen(). Например:
fclose( $fp );
- feof() - проверка конца файла. Аргумент: указатель файла.
- fgetc() - чтение очередного символа из файла. Аргумент: указатель файла.
- fgets() - чтение очередной строки файла. Аргументы: указатель файла
и длина считываемой строки. Операция прекращается либо после считывания
указанного количества символов, либо после обнаружения конца строки или файла.
Пример 4
<html> <head> <title>Чтение строк из файла</title> </head> <body> <?php $fp = fopen( "ex1.txt", "r" ) or die ( "Не удалось открыть файл" ); while ( ! feof ( $fp ) ) echo ( fgets( $fp, 1024 ) )."<br>"; ?> </body> </html>
- fread() - общая функция чтения из файла. Аргументы: указатель файла и количество считываемых символов.
- fseek() - отступ от начала файла. Аргументы: указатель файла
и смещение.
Пример 5
<html> <head> <title>Вывод на экран второй половины файла</title> </head> <body> <?php $f = "ex1.txt"; $fp = fopen( $f, "r" ) or die ( "Не удалось открыть $f" ); $fsize = filesize( $f ); $half = (int)( $fsize / 2 ); fseek ( $fp, $half ); echo ( fread( $fp, ($fsize - $half) ) ); ?> </body> </html>
- fputs() - запись строки в файл. Аргументы: указатель файла и строка.
- fwrite() - полный аналог функции fputs( ).
Пример 6
<html> <head> <title>Запись и добавление в файл</title> </head> <body> <?php $fp = fopen( "ex2.txt", "w" ) or die ( "Не удалось открыть файл" ); fputs( $fp, "Запись в файл\n" ); fclose( $fp ); $fp = fopen( "ex2.txt", "a" ) or die ( "Не удалось открыть файл" ); fputs( $fp, "Добавление в конец файла" ); fclose( $fp ); ?> </body> </html>
- flock() - блокирует файл, т.е. не позволяет другим пользователям
читать этот файл или писать в него, пока тот, кто наложил блокировку не
закончит работу с данным файлом.
Аргументы: указатель файла и номер режима блокировки.
1 Можно читать, нельзя писать 2 Нельзя ни читать, ни писать 3 Снятие блокировки Пример 7
<html> <head> <title>Блокировка файла</title> </head> <body> <?php $fp = fopen( "ex1.txt", "a" ) or die ( "Не удалось открыть файл" ); flock( $fp, 2 ); // Полная блокировка // Запись в файл flock( $fp, 3 ); // Снятие блокировки fclose( $fp ); ?> </body> </html>
Блокировка с помощью flock() не является абсолютной. С ней будут считаться только те программы, которые тоже используют эту функцию.
В PHP версии 4.3.0 появились новые удобные функции работы с файлами:
- file_get_contents() - прочитать весь файл или URL
- file_put_contents() - записать файл
Работа с каталогами
В PHP есть несколько функций для работы с каталогами:
- mkdir() - создание каталога. Аргументы: путевое имя каталога и
режим доступа. Режим доступа - восьмеричное число из трех цифр с ведущим нулем.
Первая цифра - право доступа для владельца, вторая - для группы, третья -
для всех остальных. В системе Windows режим доступа игнорируется.
В системе UNIX определены следующие права доступа:
0 Нет доступа 1 Доступ для запуска 2 Доступ для записи 3 Доступ для записи и запуска 4 Доступ для чтения 5 Доступ для чтения и запуска 6 Доступ для чтения и записи 7 Полный доступ Например, право полного доступа для владельца, чтения и запуска для группы и запуска для всех остальных:
mkdir( "testdir", 0751 );
- rmdir() - удаление каталога. Аргумент: путевое имя каталога. Удалить можно лишь пустой каталог при наличии права на это. При успешном выполнении функция возвращает true.
- opendir() - открытие каталога. Аргумент: путевое имя каталога. В случае возникновения ошибки функция возвращает false. Ошибка при открытии может быть вызвана тем, что каталог не существует или программа не имеет права его читать.
- readdir() - чтение каталога. Аргумент: путевое имя каталога.
Возвращает строку, содержащую имя найденного файла или подкаталога.
По достижении конца каталога функция возвращает false.
Пример 8
<html> <head> <title>Чтение каталога</title> </head> <body> <?php $d = "testdir"; $dh = opendir( $d ) or die ( "Не удалось открыть каталог $d" ); while ( $f = readdir( $dh ) ) echo "$f<br>"; ?> </body> </html>
Проверочное выражение цикла сработает не так, как хотелось бы, если в каталоге есть файл с именем "0". В таком случае имя "0" будет преобразовано в 0, что вызовет завершение цикла. Избежать подобного можно, если принять дополнительные меры безопасности, изменив проверочное выражение:
gettype( $f = readdir( $dh ) ) != "boolean"
Помимо использования функция fgetc() fgets() fgetss(), Вы можете использовать
$file = file($filename). Она читает $filename в массив($file).
Пример:
$file=file($filename); for ($i=0; $i<=count($file); $i++) { echo $file[$i], "<br />"; }
Передача файла с сервера. Скачать файл. DownLoad.
Ручной Download, или как скриптом открыть пользователю окошко сохранения файла.
Чтобы в браузере открылся диалог "Сохранить файл" с названием файла file.dat, скрипт должен послать такие
заголовки:
header("Content-Disposition: attachment; filename=file.dat"); header("Content-Type: application/x-force-download; name=\"file.dat\"");
Готовый пример отправки файла с диска:
<?php
$filename = "DownloadedFile.mp3"; // имя файл предложенное для сохранения в окне браузера
$myFile = $_SERVER['DOCUMENT_ROOT']."/my/file.mp3"; // файл на серевере
$mm_type="application/octet-stream";
header("Cache-Control: public, must-revalidate"); // кешировать
header("Pragma: hack");
header("Content-Type: " . $mm_type);
header("Content-Length: " .(string)(filesize($myFile)) );
header('Content-Disposition: attachment; filename="'.$filename.'"');
header("Content-Transfer-Encoding: binary");
readfile($myFile); // прочитать файл и отправить в поток
?>
Не мешало бы также ссылаться на скрипт как http://.../download.php?file.dat, иначе браузеры, основанные на Mozilla, могут попытаться записать файл как file.dat.php. или указать атрибут download:
<a href="имя.php" download="file.dat">Скачать</a>
Примечание: Не используйте заголовок header("Cache-Control: no-cache") в таких скриптах, большинство версий Internet Explorer не смогут скачать файл.
Следующий пример скрипта демонстрирует как организовать поддержку докачки:
Предполагается, что $cd - путь к файлу, $fn - имя файла
<?php
$filename = $cd."/".$fn;
if (!file_exists($filename))
{
header ("HTTP/1.0 404 Not Found");
exit;
}
$fsize = filesize($filename);
$ftime = date("D, d M Y H:i:s T", filemtime($filename));
$fd = @fopen($filename, "rb");
if (!$fd){
header ("HTTP/1.0 403 Forbidden");
exit;
}
// Если запрашивающий агент поддерживает докачку
if ($HTTP_SERVER_VARS["HTTP_RANGE"]) {
$range = $HTTP_SERVER_VARS["HTTP_RANGE"];
$range = str_replace("bytes=", "", $range);
$range = str_replace("-", "", $range);
if ($range) {fseek($fd, $range);}
}
$content = fread($fd, filesize($filename));
fclose($fd);
if ($range) {
header("HTTP/1.1 206 Partial Content");
}
else {
header("HTTP/1.1 200 OK");
}
header("Content-Disposition: attachment; filename=$fn");
header("Last-Modified: $ftime");
header("Accept-Ranges: bytes");
header("Content-Length: ".($fsize-$range));
header("Content-Range: bytes $range-".($fsize -1)."/".$fsize);
header("Content-type: application/octet-stream");
print $content;
exit;
?>
Функции для работы с каталогами
- chdir() - Сменить каталог boolean chdir (string str)
- chroot() - Сменить корневой каталог boolean chroot (string str)
- closedir() - Освободить дескриптор каталога void closedir (resourse catalog)
Изменяет текущий каталог PHP на указанный в качестве параметра str. Возвращает TRUE в случае успешного завершения, FALSE в случае возникновения ошибки
Изменяет корневой каталог текущего процесса на переданный в качестве параметра str. Возвращает TRUE в случае успешного завершения, FALSE в случае возникновения ошибки..
Замечание: Для Windows-платформ эта функция не реализована.
Закрывает поток, связанный с каталогом и переданный в качестве параметра catalog. Перед использованием данной функции, поток должен быть открыт с помощью функции opendir().
dir - Класс directory
class dir { dir (string str) string path resource handle string read (void) void rewind (void) void close (void) }
Псевдо-объектно-ориентированный механизм для чтения каталога, переданного в параметре каталог. С момента открытия каталога становятся доступными два свойства класса. Свойство "handle" может быть использовано с другими функциями для работы с каталогами, например, с функциями readdir(), rewinddir() и closedir(). Свойство "path" содержит путь к открытому каталогу. Доступны три метода: read, rewind and close.
Пожалуйста, обратите внимание на способ, которым осуществляется проверка значения, возвращаемого методами класса dir() в примере, приведенном ниже. В этом примере проводится проверка значения на идентичность (выражения идентичны, когда они равны и являются одного типа - за более подробной информацией обратитесь к главе Операторы сравнения) значению FALSE, поскольку в ином случае, любой элемент каталога, чье имя может быть выражено как FALSE, остановит цикл.
Пример кода:
<?php $d = dir("/etc"); echo "Дескриптор: ".$d->handle."<br>\n"; echo "Путь: ".$d->path."<br>\n"; while (false !== ($entry = $d->read())) { echo $entry."<br>\n"; } $d->close(); ?>
Замечание: Порядок, в котором метод "read" возвращает элементы каталога, зависит от операционной системы.
Замечание: Также, PHP автоматически определяет внутренний класс Directory, что означает, что вы не сможете определять собственные классы с таким же именем.
Возвращает имя текущего рабочего каталога.
Возвращает дескриптор каталога для последующего использования с функциями closedir(), readdir() и rewinddir().
Если путь не существует или каталог, расположенный по указанному пути, не может быть открыт вследствие правовых ограничений или ошибок файловой системы, функция opendir() возвращает значение FALSE и генерирует сообщение PHP об ошибке уровня E_WARNING. Вы можете запретить вывод сообщения об ошибке, предварив имя функции opendir() символом '@'.
Пример кода
<?php $dir = "/tmp/"; // Открыть заведомо существующий каталог // и начать считывать его содержимое if (is_dir($dir)) { if ($dh = opendir($dir)) { while (($file = readdir($dh)) !== false) { print "Файл: $file : тип: " . filetype($dir . $file) . "\n"; } closedir($dh); } } ?>
Начиная с версии PHP 4.3.0, параметр путь может также являться любым URL'ом, обращение к которому приводит к получению списка его файлов и каталогов. Однако, данный способ работает только при использовании url-упаковщика file://. В версии PHP 5.0.0 была добавлена поддержка url-упаковщика ftp://.
Возвращает имя следующего по порядку элемента каталога. Имена элементов возвращаются в порядке, зависящем от файловой системы.
Обратите внимание на способ проверки значения, возвращаемого функцией readdir() в приведенном ниже примере. В этом примере осуществляется проверка значения на идентичность (выражения идентичны, когда они равны и являются значениями одного типа - за более подробной информацией обратитесь к главе Операторы сравнения) значению FALSE, поскольку в ином случае, любой элемент каталога, чье имя может быть выражено как FALSE, остановит цикл (например, элемент с именем "0").
Пример кода
<?php // Вывести список всех файлов в каталоге // Оператор !== не существовал до версии 4.0.0-RC2 if ($handle = opendir('/path/to/files')) { echo "Дескриптор каталога: $handle\n"; echo "Файлы:\n"; /* Именно этот способ чтения элементов каталога является правильным. */ while (false !== ($file = readdir($handle))) { echo "$file\n"; } // Этот способ НЕВЕРЕН. while ($file = readdir($handle)) { echo "$file\n"; } closedir($handle); } ?>
Обратите внимание, что функция readdir() также возвращает элементы с именами, и, если вы не хотите получать эти значения, просто отбрасывайте их:
Пример кода
<?php if ($handle = opendir('.')) { while (false !== ($file = readdir($handle))) { if ($file != "." && $file != "..") { echo "$file\n"; } } closedir($handle); } ?>
Сбрасывает поток каталога, переданный в параметре catalog таким образом, чтобы тот указывал на начало каталога
Возвращает массив, содержащий имена файлов и каталогов, расположенных по пути, переданном в параметре catalog. Если каталог не является таковым, функция возвращает логическое значение FALSE и генерирует сообщение об ошибке уровня E_WARNING.
По умолчанию, сортировка производится в алфавитном порядке по возрастанию. Если указан необязательный параметр order (равен 1), сортировка производится в алфавитном порядке по убыванию. Пример кода
<?php $dir = '/tmp'; $files1 = scandir($dir); $files2 = scandir($dir, 1); print_r($files1); print_r($files2); ?>
Результатом будет нечто вроде:
Array ( [0] => . [1] => .. [2] => bar.php [3] => foo.txt [4] => somedir ) Array ( [0] => somedir [1] => foo.txt [2] => bar.php [3] => .. [4] => . )
Пример кода
<?php // Альтернативный вариант функции scandir() для PHP 4 $dir = "/tmp"; $dh = opendir($dir); while (false !== ($filename = readdir($dh))) { $files[] = $filename; } sort($files); print_r($files); rsort($files); print_r($files); ?>