7.9. Чтение и запись в файлы
Операции обмена данными с файлами всегда выполняются примерно по одному и тому же алгоритму: открытие потока на файл, чтение/запись файла и закрытие потока. При открытии потока в ваше распоряжение предоставляется ресурс, с помощью которого можно ссылаться на открытый поток. Каждый раз, когда необходимо произвести операцию чтения или записи в файл, используется идентификатор потока. Внутренне PHP для ссылки на всю информацию, необходимую для обмена данными с файлом, использует целое число.
Для того чтобы открыть файл из локальной файловой системы, используется функция fopen. Она принимает имя файла и строку, в которой задается режим обмена. Это может быть r (только для чтения), или w (только для записи), или другие режимы. Если перед полным именем файла, включая и имя узла, указать префикс http:/ / или ftp://, можно задать адрес в Internet. Функции работы с файлами описываются в главе 9, "Операционная система".
Две другие обычно используемые функции создают потоки файлов. С помощью функции popen можно задать каналы, а с помощью функции fsockopen - открыть соединение с использованием сокета. Если разработчик имеет опыт работы с ОС Unix, то он может рассматривать каналы как переменные потоки данных, устанавливаемые между работающими программами. Общепринятым методом отправки почты в Perl является открытие канала к программе sendmail, предназначенной для отправки электронной почты по Internet. Так как PHP имеет множество встроенных функций, он редко пользуется каналами, но при этом совсем нелишне будет знать, что такая возможность все же имеется.
С помощью функции fsockopen можно открыть поток на файл, который позволяет обмениваться данными по соединению TCP/IP. Эта функция принимает имя узла и номер порта и делает попытку установить соединение. (Она описывается в главе 10, "Операции ввода-вывода на сетевом уровне", вместе с остальными сетевыми функциями.)
После того как файловый поток открыт, с этим файлом можно выполнять операции чтения/записи. Для этих целей можно воспользоваться функциями fgets и fputs (листинг 7.5). Обратите внимание на то, как в этом сценарии для получения каждой строки из файла используется цикл while. В нем с помощью функции feof проверяется достижение конца файла. После завершения обработки файла вызывается функция fclose. При этом PHP очищает временную память, которая была занята под хранение информации об открытом файле. 

Листинг 7.5. Чтение и запись в файл

<?php
// открыть файл для записи $filename = "/tmp/data.txt"; if(!($myFile = fopen($filename, "w")))
{
print("Ошибка:");
print("невозможно создать файл '$filename' n"); exit;
}
// записать строки в файл
fputs($myFile, "Сохранить эту строку n");
fputs($myFile, "Эту строку сохранить тоже^"),-
// закрыть файл
fclose($myFile);
// открыть файл для чтения
if(!($myFile = fopen($filename, "r")))
{
print(" Ошибка:");
print("невозможно прочитать файл '$filename' n"); exit;
}
while(!feof($myFile))
{
//прочитать строку из файла $myLine = fgets($myFile, 255); print("$myLine<br>n");
}
// закрыть файл fclose($myFile);
?>
Следует помнить, что PHP выполняет сценарий под управлением определенного пользователя, обычно им является пользователь "nobody". Этот пользователь, вероятно, не имеет разрешения на создание файлов в ваших Web-каталогах. Позаботьтесь о том, чтобы ваши сценарии производили запись в каталог, с которым могут работать удаленные пользователи. В простейшем случае, если сохраняется какая-то информация наподобие информации из гостевой книги, вы можете позволить любому посетителю просмотреть весь файл. Серьезнее дело обстоит в случае обработки PHP таких файлов данных, которые позволят удаленным пользователям создавать PHP-код, который может нанести вашей системе определенный ущерб, например похитить данные. И здесь существует достаточно простое решение: эти файлы следует размещать за пределами дерева документов Web-узла.