САМОУЧИТЕЛЬ PHP 4

       

Открытие файла


Как и в Си, работа с файлами в PHP разделяется на три этапа. Сначала файл открывается в нужном режиме, при этом возвращается некое целое число, служащее идентификатором открытого файла (дескриптор файла). Затем настает очередь команд работы с файлом (чтение или запись, или и то и другое), причем они "привязаны" уже к дескриптору файла, а не к его имени. После этого файл лучше всего закрыть (хотя это можно и не делать, поскольку PHP автоматически закрывает все файлы по завершении сценария).

int fopen(string $filename, string $mode, bool $use_include_path=false)

Открывает файл с именем $filename в режиме $mode и возвращает дескриптор открытого файла. Если операция "провалилась", то, как это принято, fopen() возвращает false. Впрочем, мы можем не особо беспокоиться, проверяя выходное значение на ложность— вполне подойдет и проверка на ноль, потому что дескриптор 0 в системе соответствует стандартному потоку ввода, а он, очевидно, никогда не будет открыт функцией fopen() (во всяком случае, пока не будет закрыт нулевой дескриптор, а это делается крайне редко). Необязательный параметр $use_include_path

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

и require. Обычно этот параметр не используют.

Параметр $mode может принимать следующие значения:

r    r — файл открывается только для чтения. Если файла не существует, вызов регистрирует ошибку. После удачного открытия указатель файла устанавливается на его первый байт, т. е. на начало;

r    r+ — файл открывается одновременно на чтение и запись. Указатель текущей позиции устанавливается на его первый байт. Как и для режима r, если файла не существует, возвращается false. Следует отметить, что если в момент записи указатель файла установлен где-то в середине файла, то данные запишутся прямо поверх уже имеющихся, а не "раздвинут"

их, при необходимости увеличив размер файла. Будьте внимательны;


r    w — создает новый пустой файл. Если на момент вызова уже был файл с таким именем, то он предварительно уничтожается. В случае неверно заданного имени файла вызов, как нетрудно догадаться, "проваливается";

r    w+ — аналогичен r+, но если файла изначально не существовало, создает его. После этого с файлом можно работать как в режиме чтения, так и записи. Если файл существовал до момента вызова, его содержимое удаляется;

r    a — открывает существующий файл в режиме записи, и при этом сдвигает указатель текущей позиции за последний байт файла. Этот режим полезен, если требуется что-то дописать в конец уже имеющегося файла. Как водится, вызов неуспешен в случае отсутствия файла;



r    a+ — открывает файл в режиме чтения и записи, указатель файла устанавливается на конец файла, при этом содержимое файла не уничтожается. Отличается от a тем, что если файла изначально не существовало, то он создается. Этот режим полезен, если вам нужно что-то дописать в файл (например, в журнал), но вы не знаете, создан ли уже такой файл;

Но это еще не полное описание параметра $mode. Дело в том, что в конце любой из строк r, w, a, r+, w+ и a+ может находиться еще один необязательный символ — b или t. Если указан b (или не указан вообще никакой), то файл открывается в режиме бинарного чтения/записи. Если же это t, то для файла устанавливается режим трансляции символа перевода строки, т. е. он воспринимается как текстовый.



О режиме t

нет ни слова в документации PHP (во всяком случае, на момент написания этих строк), однако, как показывают мои тесты, он работает на всех системах.

Чтобы проиллюстрировать это, давайте рассмотрим пример сценария. Он будет работать по-разному в зависимости от того, в каком режиме мы откроем файл: в бинарном или текстовом. Забегая вперед, замечу, что функция fgets() читает из файла очередную строку.

Листинг 15.1. Сценарий test.php:

работа с текстовыми файлами



<?

// Получает в параметрах строку и возвращает через пробел коды

// символов, из которых она состоит

function MakeHex($st)

{  for($i=0; $i<strlen($st); $i++) $Hex[]=sprintf("%2X",ord($st[$i]));

   return join(" ",$Hex);

}

// Открываем файл разными способами

$f=fopen("test.php","r");  // бинарный режим

echo MakeHex(fgets($f,100)),"<br>\n";

$f=fopen("test.php","rt"); // текстовый режим

echo MakeHex(fgets($f,100)),"<br>\n";

?>

Первая строчка файла test.php состоит всего из двух символов — это < и ?. За ними должен следовать маркер конца строки. Сценарий показывает, как выглядит этот маркер, т. е. состоит ли он из одного или двух символов.

Запустим этот сценарий в Unix. Мы получим две одинаковые строки, которые выводят операторы echo:

3C 3F 0A

3C 3F 0A

Отсюда следует, что в этой системе физический конец строки обозначается одним символом — кодом 0x0A, или \n (коды 0x3C и 0x3F соответствуют символам < и ?). В то же время, если запустить сценарий в Windows, мы получим такой результат:

3C 3F 0D 0A

3C 3F 0A

Как видите, бинарное и текстовое чтение дали разные результаты! В последнем случае произошла трансляция маркера конца строки.

Как уже говорилось, можно предварять имя файла строкой http:// или ftp://, при этом прозрачно будет осуществляться доступ к файлу с удаленного хоста.

В случае HTTP-доступа PHP открывает соединение с указанным сервером, а также посылает ему нужные заголовки: Host и GET[E65] . После чего при помощи файлового дескриптора из удаленного файла можно читать обычным образом — например, посредством все той же функции fgets().

Если же вы открываете FTP-файл, то в него можно производить либо запись, либо читать из него, но не и то и другое одновременно. Кроме того, FTP-сервер должен поддерживать пассивный режим передачи (впрочем, большинство серверов его поддерживают). Не забудьте также указать логин и пароль, как это сделано в примерах ниже.



Дам небольшой совет: не используйте обратные слэши \ в именах файлов, как это принято в DOS и Windows. Просто забудьте про этот архаизм. Поможет вам в этом PHP, который незаметно в нужный момент переводит прямые слэши / в обратные (разумеется, если вы работаете под Windows). Если же вы все-таки не можете обойтись без обратного слэша, не забудьте его удвоить, потому что в строках он воспринимается как спецсимвол:

$fp = fopen ("c:\\windows\\hosts", "r");

Еще раз предупреждаю: этот способ не переносим между операционными системами и из рук вон плох. Не используйте его!

Вот несколько примеров:

// Открывает файл на чтение

$f = fopen("/home/user/file.txt", "r") or die("Ошибка!");

// Открывает HTTP-соединение на чтение

$f = fopen("http://www.php.net/", "r") or die("Ошибка!");

// Открывает FTP-соединение с указанием логина и пароля для записи

$f = fopen("ftp://user:password@example.com/", "w") or die("Ошибка!");


Содержание раздела