Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

PHP5_nachinayushim

.pdf
Скачиваний:
29
Добавлен:
20.03.2015
Размер:
26.79 Mб
Скачать

294 Глава 7

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

PHP предоставляет две группы связанных с файлами функций, которые отличают+ ся способом обработки файлов: первая группа функций использует дескриптор файла (file handle) или, как его часто называют, указатель файла (file pointer); вторая группа ис+ пользует непосредственно строковое имя файла. То же касается PHP+функций, свя+ занных с обработкой каталогов.

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

Дескриптор файла содержится в переменной (имя которой создается так же, как имя любой другой PHP+переменной; в приведенных здесь примерах эта переменная обычно имеет имя $fp). Целое значение, содержащееся в данной переменной, иден+ тифицирует соединение с тем файлом, с которым в данный момент работает сцена+ рий. Например, как только с помощью функции fopen() открывается какой+либо файл, появляется возможность записывать в этот файл данные, используя функцию fwrite(). Функции fwrite() требуется дескриптор файла (в данном случае $fp), указывающий на файл, с которым функция должна работать:

fopen($fp, "myfile.txt", "w+"); fwrite($fp, 'Hello world!');

В данном случае $fp ++++++ переменная, представляющая дескриптор файла (в нее за+ писывается целое значение, когда используется функция fopen() для открытия ука+ занного в первой строке файла). Функция fwrite() записывает в представленный данным дескриптором файл текст, содержащийся в ее втором аргументе (вторая строка примера).

С другой стороны, функция file(), которая используется для считывания данных из файла, принимает строковый аргумент, содержащий путь к данному файлу:

$lines = file('./data.txt');

В следующих разделах эти новые функции описываются подробнее.

Все упомянутые в данной главе функции возвращают значение True, если заданная операция выполнена успешно, и False ****** в противном случае.

Рассмотрим функции для работы с файлами.

Открытие и закрытие файлов

Работа с файлами обычно состоит из трех этапов:

1.Открытие файла и связывание с ним дескриптора.

2.Чтение данных из файла или запись данных в файл с помощью дескриптора.

3.Закрытие файла с помощью дескриптора.

Функция fopen()

Функция fopen() используется для открытия файла и возвращает дескриптор, связанный с открытым файлом. Она принимает два или три аргумента: имя файла, режим и необязательный параметр use_include_path.

Файлы и каталоги 295

Дескриптор файла помогает определить, был ли данный файл успешно открыт (если это так, то дескриптор файла представляет собой положительное целое число, в противном случае он равен нулю). Операции с файлами часто вызывают ошибки, по+ этому всегда следует принимать во внимание, что необходимая операция может быть выполнена неверно. Хорошей практикой является использование процедуры для об+ работки ошибок, которая в случае возникновения ошибки (например, сценарий не имеет необходимых прав для доступа к данному файлу или файл вообще не существу+ ет) завершит работу сценария аккуратно и желательно с подходящим сообщением. Например, учитывая то, как PHP интерпретирует целые числа в контексте булевых операций, можно использовать тот факт, что значение дескриптора файла преобра+ зуется в True в случае успешного завершения операции и в False ++++++ в случае ошибки. Это позволяет проверить открытие файла с помощью следующего кода:

$fp = fopen("./data.txt", "r");

if(!$fp) die ("Невозможно открыть файл");

Этот код при желании можно переписать так:

if(!($fp = fopen("./data.txt", "r"))) die ("Невозможно открыть файл");

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

Первый аргумент функции fopen() определяет имя файла, который требуется открыть. Значением этого аргумента может быть имя файла, относительный (например, “./data.inc”) или абсолютный (“/myfiles/data.inc”) путь к файлу. (Что произойдет, если указать только имя файла, например, data.txt, будет показа+ но далее при рассмотрении аргумента use_include_path.) Данная функция также позволяет указать файл на удаленном узле и открывает его через HTTP или FTP URL, как показано в примере ниже:

if(!($fp = fopen("http://www.whatyoumaycallit.com/index.html", "r"))) die ("Невозможно открыть файл.");

if(!($fp = fopen("ftp://ftp.whatyoumaycallit.com/pub/index.txt", "r"))) die ("Невозможно открыть файл.");

Удаленный файл можно открыть только для чтения ++++++ его невозможно модифи+ цировать.

Нотация относительного пути может запутать тех, кто не знаком

сфайловыми операциями в командной строке Unix или Windows. В от* носительном пути к файлу точка (.) означает текущий каталог, а две точки (..) ****** родительский каталог. Например, путь ./data.txt указывает на файл data.txt в том же каталоге, что и сценарий, а путь ../data.txt указывает на файл data.txt, находящийся в каталоге более высокого уровня. Путь ../../../data.txt указывает на файл data.txt, кото* рый расположен в каталоге тремя уровнями выше каталога сценария. Абсолютный путь отличается от относительного тем, что начинается

скосой черты (/), которая указывает на то, что путь задан относитель* но корневого каталога файловой системы, а не относительно располо* жения сценария. Например, запись C:/Inetpub/wwwroot/index.php представляет собой абсолютный путь.

296 Глава 7

Второй аргумент функции fopen() (именованный режим) определяет то, как бу+ дет использоваться открываемый файл. Задав одно из следующих значений, можно открыть файл только для чтения, для чтения и записи или только для записи.

Значение

Описание

rОткрытие файла только для чтения. Указатель позиции в файле помещается в начало файла

r+ Открытие файла для чтения и записи. Указатель позиции в файле помещается в начало файла

wОткрытие файла только для записи. Любые имеющиеся в файле данные будут утеряны. Если файл не существует, то PHP попытается его создать

w+ Открытие файла для чтения и записи. Любые имеющиеся в файле данные будут утеряны. Если файл не существует, то PHP попытается его создать

aОткрытие файла только для дополнения. Данные записываются в конец существующего файла. Если файл не существует, то PHP попытается его создать

a+ Открытие файла для чтения и дополнения. Данные записываются в конец существующего файла. Если файл не существует, то PHP попытается его создать

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

Аргумент режима в функции fopen() может также принимать значение b, которое указывает на то, что открытый файл необходимо интерпретировать как двоичный. В таких платформах, как Linux, которые интерпретируют текстовые и двоичные файлы одинаково, это значение не играет роли, однако в Windows оно может оказаться полез+ ным, потому что Windows (а также Apple Macintosh) по+разному устанавливает символы конца строки для текстовых и двоичных файлов (в Windows используется последова+ тельность CRLF, в Macintosh ++++++ CR, а в Linux ++++++ LF). По умолчанию в функции fopen() (начиная с версии 4.3.2 PHP) используется бинарный режим для всех платформ. Это оз+ начает, что преобразование символа конца строки не выполняется. Рекомендуется ис+ пользовать значение b как часть аргумента режима, чтобы код мог использовать те сим+ волы конца строки, которые подходят для платформы, на которой он выполняется.

Третий (необязательный) аргумент функции fopen() называется use_include_path (пути для подключаемых файлов). Если его значение равно 1 и указано только имя файла, но не путь к нему, то функция будет искать данный файл сначала в том ка+ талоге, где расположен сценарий, а затем в каталогах, указанных в параметре include_path файла php.ini.

Пути для подключаемых файлов особенно полезно указывать, если необходимо за+ дать каталог, в котором расположены подключаемые файлы, часто используемые сценариями сайта. Предположим, что параметру include_path файла php.ini при+ своено значение /home/apache/inc и выполняется следующий вызов функции:

fopen("data.txt", "r", 1);

Если в таком случае функция не сможет найти файл data.txt в текущем каталоге, то она продолжит поиск файла в каталоге /home/apache/inc.

Файлы и каталоги 297

Функция fclose()

Как только работа с файлом закончена, файл необходимо закрыть. Это можно сде+ лать с помощью функции fclose(), передав ей в качестве единственного аргумента дескриптор открытого файла:

fclose ($fp)

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

Получение информации о файле

Файлы содержат множество сведений о самих себе, например, размер, дату измене+ ния, имя владельца и т.д. В PHP имеется функция stat(), позволяющая получить ин+ формацию о файле. Для этого ей необходимо передать в качестве аргумента имя файла.

Функция stat() возвращает индексированный массив, содержащий статистиче+ скую информацию о файле. В возвращаемом функцией массиве имеется 13 элементов:

Индекс массива

Ассоциативное имя

Информация

 

 

 

0

Dev

Номер устройства

1

Ino

Номер индексного узла (inode)

2

Mode

Режим защиты индексного узла

3

nlink

Количество ссылок

4

uid

Пользовательский идентификатор владельца

 

 

файла (Userid)

5

gid

Идентификатор группы владельца файла

6

rdev

Тип устройства (в случае inode-устройства)

7

size

Размер в байтах

8

atime

Время последнего доступа к файлу

9

mtime

Время последней модификации содержимого файла

10

ctime

Время последнего изменения inode-информации

 

 

файла

11

blksize

Размер блока ввода-вывода файловой системы

12

blocks

Количество используемых блоков

 

 

 

Следующий фрагмент кода показывает, как использовать функцию stat() для по+ лучения размера файла в байтах (предполагается, что файл myfile.txt существует):

$my_file_stats = stat("myfile.txt"); $my_file_size = $my_file_stats[7];

ВWindows и Macintosh доступна не вся информация, предоставляемая этой функцией.

Вчастности, если используется Web+сервер Personal Web Server на платформе Windows 98, то в массиве, возвращаемом stat(), не будет идентификатора группы и идентифика+ тора пользователя, потому что в данной системе они не используются. Подробнее эта тема освещается в данной главе в разделе ‘‘Принадлежность и права доступа к файлам’’.

298 Глава 7

Чтение и запись файлов

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

Функция fread()

Функцию fread() можно использовать для получения строки символов из файла. Функция принимает два аргумента: дескриптор файла $fp и целое число $length. Функция считывает из файла, указанного посредством дескриптора $fp, $length бай+ тов и возвращает их в виде строки. Предположим, например, что открывается файл:

$fp = fopen("data.txt", "r")

а затем используется следующий вызов:

$data = fread($fp, 10);

Функция fread() получит первые 10 байтов из файла data.txt и запишет их в переменную $data как строку символов.

Функция перемещает указатель позиции в файле на 10 байтов вниз, поэтому, если повторить тот же вызов fread(), то в переменную $data будут записаны следующие 10 байтов файла. Если в файле осталось менее 10 непрочитанных байтов, то функция прочитает и возвратит столько байтов, сколько осталось.

Функция fwrite()

Функцию fwrite() можно использовать для записи данных в файл. Эта функция принимает два обязательных аргумента: дескриптор файла ($fp) и строку (строку текста, которая будет записана в файл), после чего записывает содержимое строки в файл, заданный дескриптором. При этом функция возвращает количество записан+ ных байтов (или -1 в случае ошибки). Например, после открытия файла с помощью вызова $fp = fopen(“data.txt”, “w”) можно использовать такой код:

fwrite($fp, "ABCxyz");

В результате в начало файла data.txt будет записана строка ”ABCxyz”. Посколь+ ку при открытии файла использовался режим только для записи, вся информация, ко+ торая была в файле до этого, будет утеряна (а если файл не существовал, то будет соз+ дан новый файл data.txt); однако повторение данного вызова приведет к тому, что в конец файла будут записаны те же шесть байтов, и в файле будет записана строка ”ABCxyzABCxyz”. Это также связано с работой указателя позиции в файле.

Если указать в качестве третьего аргумента целое значение length, то функция прекратит работу сразу после записи length байтов (предполагается, что это случит+ ся раньше, чем будет достигнут конец строки). Например, код

fwrite($fp, "abcdefghij", 4);

запишет в файл, заданный $fp, первые четыре байта строки “abcdefghij” (т.е. “abcd”). Если строка содержит менее чем length байтов, то она будет записана в файл полностью.

Рассмотрим практический пример.

Практика Простой счетчик посещений

Очень распространенной разновидностью Web+сценариев является счетчик посе+ щений, который используется для того, чтобы показывать на Web+странице количество

Файлы и каталоги 299

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

<?php //hit_counter01.php

$counter_file = "./count.dat";

if(!($fp = fopen($counter_file, "r"))){

die ("Невозможно открыть файл $counter_file.");

}

$counter = (int) fread($fp, 20); fclose($fp);

$counter++;

echo "Вы – посетитель № $counter.";

$fp = fopen($counter_file, "w"); fwrite($fp, $counter); fclose($fp);

?>

Сохраните данный код как hit_counter01.php и вызовите эту страницу в брау+ зере. Пример ее работы показан на рис. 7.1.

Рис. 7.1.

При запуске сценария возникает ошибка. Это не удивительно. Сценарий предпола+ гает, что файл count.dat существует и расположен в текущем каталоге, т.е. в каталоге, из которого запускается сценарий. Если такого файла в данном каталоге нет, то возни+ кает ошибка и сценарий прекращает работу, отображая на экране сообщение об ошибке.

300 Глава 7

Создать файл можно путем сохранения пустого текстового файла в текстовом ре+

дакторе (например, в Notepad в Windows; не забудьте выбрать пункт Все файлыв списке Тип файлов, в противном случае к имени файла будет добавлено расширение .txt)

или в Unix+подобной системе, используя команду touch:

> touch count.dat

После создания файла можно снова проверить работу сценария. Примерный ре+ зультат показан на рис. 7.2.

Рис. 7.2.

При желании в файле count.dat можно задать начальное количество посещений. Если данный сценарий используется на Linux+платформе, то следует убедиться, что Web+сервер имеет права на чтение и запись данного файла.

Как это работает

Прежде всего, файл count.dat (в текущем каталоге) открывается функцией fopen() в режиме только для чтения:

$counter_file = "./count.dat";

if(!($fp = fopen($counter_file, "r"))){

die ("Невозможно открыть файл $counter_file.");

Возвращенный функцией fopen() дескриптор файла присваивается переменной $fp, которую после этого можно использовать для обращения к данному открытому файлу. Функция возвращает значение False в случае ошибки, поэтому если заданный файл не существует или во время его открытия возникла какая+либо ошибка, то сценарий завершится с соответствующим сообщением об ошибке.

Файлы и каталоги 301

Затем сценарий использует дескриптор файла для считывания числа посещений из открытого файла. Как видно из кода, сценарий вызывает функцию fread() для считывания 20 байтов из файла данных (20 байтов достаточно для хранения, как ми+ нимум, одного миллиона посещений):

$counter = (int) fread($fp, 20);

Так как функция fread() возвращает строковое значение, последнее число посе+ щений, считанное из файла, необходимо конвертировать в целое значение, поэтому применяется функция преобразования типа (int).

Затем функция fclose() закрывает файл, связанный с дескриптором $fp, запи+ сывая все не записанные данные в файл:

fclose($fp);

После закрытия файла сценарий увеличивает счетчик и сообщает посетителю о количестве посещений данной страницы:

$counter++;

echo "Вы – посетитель № $counter.";

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

$fp = fopen($counter_file, "w"); fwrite($fp, $counter); fclose($fp);

Вызов функции fwrite() с переменной $counter в качестве второго аргумента гарантирует точную длину строки, записываемой в файл, поэтому аргумент длины указывать необязательно. Затем файл закрывается с помощью функции fclose().

Можно подойти к проблеме подсчета посетителей творчески и создать графиче+ ский счетчик. Простой тестовый счетчик, используемый совместно с набором изо+ бражений, можно превратить в графический счетчик. Например, если для каждой цифры в счетчике имеется изображение (файлы 1.gif, 2.gif, 3.gif и т.д.), то каж+ дое численное значение можно использовать для указания графического файла, свя+ занного с данной цифрой:

<?php //hit_counter02.php

$counter_file = "./count.dat"; $image_dir = "./images";

if(!($fp = fopen($counter_file, "r"))){

die ("Невозможно открыть файл $counter_file.");

}

$counter = (int) fread($fp, 20); fclose($fp);

$counter++;

for ($i=0; $i < strlen($counter); $i++) {

$image_src = $image_dir . "/" . substr($counter, $i, 1) . ".gif"; $image_tag_str .= "<img src= \"$image_src\" border=\"0\">";

}

echo "Вы – посетитель № $image_tag_str.";

$fp = fopen($counter_file, "w"); fwrite($fp, $counter); fclose($fp);

?>

302Глава 7

Вэтом сценарии (назовем его hit_counter02.php) добавлен цикл for для обра+ ботки возможных значений переменной $counter и связывания каждой цифры с со+ ответствующим изображением. Цикл обеспечивает обработку каждой цифры, прове+ ряя длину строки, содержащейся в переменной $counter. На рис. 7.3 показан примерный результат запуска сценария.

Рис. 7.3.

Чтение и запись символов в файлы

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

do {$one_char = fread($fp, 1); $counter .= $one_char; } while ($one_char);

Однако PHP предоставляет несколько функций, которые позволяют решить эти задачи гораздо проще:

fgetc()

feoff()

fgets()

fgetcsv()

fputs()

Функцию fgetc() можно использовать для считывания из файла по одному сим+ волу за раз. Функция fgetc() принимает один аргумент, дескриптор файла $fp,

Файлы и каталоги 303

и возвращает только один символ из связанного с данным дескриптором файла; если функция достигает конца файла, то она возвращает False. По существу, она работает так же, как и fread() ++++++ вызов:

$one_char = fgetc($fp)

эквивалентен вызову:

$one_char = fread($fp,1)

Модифицируем первоначальный счетчик с использованием в нем функции fgetc(). Для этого можно использовать такой код:

<?php //hit_counter03.php

$counter_file = "./count.dat";

if(!($fp = fopen($counter_file, "r"))) die ("Невозможно открыть файл $counter_file.");

do {

$one_char = fgetc($fp); $counter .= $one_char;

} while($one_char); $counter = (int) $counter; fclose($fp);

Чтобы считать все содержимое файла данных, используется цикл while, потому что функция fgetc() считывает из файла только один символ за раз. Кроме того, не+ обходимо знать, когда прекращать чтение, поэтому последний считанный символ за+ писывается в холостую переменную, и когда она будет равна False, цикл чтения можно прекратить. Однако в таком коде есть один дефект. Как только из файла будет считано значение "0" или " ", условие цикла не выполнится и цикл чтения прекра+ тится. Если планируется, что значение счетчика посещений будет превышать 9, то данная особенность может оказаться серьезной проблемой.

Существует другой способ определить момент завершения цикла чтения ++++++ ис+ пользование функции feof().

Функция feof() служит одной простой цели: она возвращает True, когда достига+ ет конца заданного файла (или если возникает ошибка), и False ++++++ в противном слу+ чае. Функция принимает только один аргумент ++++++ дескриптор файла:

feof($fp)

Поэтому в качестве условия цикла можно использовать логическое отрицание и проверить, таким образом, не достиг ли указатель конца данного файла:

<?php //hit_counter04.php

$counter_file = "./count.dat";

if(!($fp = fopen($counter_file, "r"))) die ("Невозможно открыть файл $counter_file."); while(!feof($fp)) $counter .= fgetc($fp);

$counter = (int) $counter; fclose($fp);

$counter++;

echo "Вы – посетитель № $counter.";

$fp = fopen($counter_file, "w"); fwrite($fp, $counter); fclose($fp);

?>

Функция feof() сообщает оператору while, когда необходимо завершить цикл (когда функция fgetc() в процессе посимвольного считывания достигает конца

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]