PHP-4 Эффективная работа


Интерфейс с файловой системой
Проверка отдельных характеристик файлов
Операции с содержимым файлов
Операции с конвейерами
Специальные и необычные функции

10.3.Операции с содержимым файлов

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

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

10.3.1. Закрытие файла: fclose

bool fclose (int fp)

Функция выполняет закрытие файла, адресуемого указателем fр. При успешном выполнении операции функция возвращает true, а при ошибке — false. Указатель файла должен быть зарегистрирован в системе и указывать на файл, открытый с помощью fopen () (см. раздел 10.3.10).

10.3.2. Достигнут ли конец файла: feof

int feof (int fp)

Возвращает true, если текущая позиция файла установлена на конец файла (EOF) или при последней операции доступа к его содержимому произошла ошибка. В про- тивном случае возвращает false.

Указатель файла должен быть зарегистрирован в системе и указывать на файл, открытый с помощью f open () (см. раздел 10.3.10).

10.3.3. Снос буферов на диск: fflush

int fflush (int fp)

Функция осуществляет принудительную запись всех файловых буферов указанного файла на физический диск. В случае успешного завершения возвращает true, а при ошибке — false.

Указатель файла должен быть зарегистрирован в системе и указывать на файл, открытый с помощью fopen () (см. раздел 10.3.10).

10.3.4. Считывание очередного символа: fgetc

string fgetc (int fp)

Функция возвращает строку, содержащую очередной символ, считанный из фай- ла, адресуемого указателем fр. В случае достижения конца файла функция возвращает false.

Указатель файла должен быть зарегистрирован в системе и указывать на файл, открытый с помощью fopen () (см. раздел 10.3.10).

См. также описания fread () (раздел 10.3.13), рореп() (раздел 10.4.) и fgets() (раздел 10.3.6).

10.3.5. Считывание строки CSV с разбором: fgetcsv

array fgetcsv (int fp, int length [, string delimiter])

Функция работает в целом аналогично fgets () (см. раздел 10.3.6) с тем отличием, что fgetcsv () автоматически разбирает строку в формате CSV (Comma Separated Values) и возвращает массив, содержащий считанные значения. В случае ошибки или при достижении конца файла функция возвращает false. По умолчанию в качестве разделителей полей используется запятая, но вы вполне можете заменить ее на любой другой символ, переданный функции в качестве третьего параметра.

примечание
       Например, при анализе естественно-языковых текстов может оказаться удобным использовать в качестве разделителя пробел.

Указатель файла должен быть зарегистрирован в системе и указывать на файл, открытый с помощью f open () (см. раздел 10.3.10).

Аргумент length должен представлять собой число, большее, чем максимальная длина строки в CSV-файле.

совет
       Пустая строка в CSV-Файле интерпретируется этой функцией как массив, состоящий из единственного нулевого (пустого) элемента. Но эта ситуация не рассматривается как ошибка!

В листинге 10.1 приведен пример загрузки и вывода на экран содержимого файла в CSV-формате.

Листинг 10.1. Загрузка файла в CSV-формате
<HTML>
<TITLE>3arpy3Ka файла в СSV-формате</ТIТLЕ>
<BODY BGCOLOR="#FFFFFF">
<FONT SIZE=+1>
<hЗ>Ассортимент товаров нашей бакалейной лавочки</hЗ>
<table border=1>
<tr><th>No.</th><th>Apтикул</th>
<th>Haименование</th><th>Ценаa</th>
<th>Ha складе</th><tr>
<?
$row = 1;
$fp = fopen ("shop.csv","r");
if (!$fp) {
       echo "Беда! Не удается найти файл с прайс-листом!";
       exit;
}
while ($data = fgetcsv ($fp, 1000, ",")) {
       $num = count ($data);
       echo "<tr><td>$row</td>";
       for ($c=0; $c<$num; $c++) {
       print "<td>".$data[$c] . "</td>"; }
      $row++; // Увеличиваем счетчик строк
echo "</tr>\n";
fclose ($fp);
?>
</table>
А вот сам файл shop.csv, в котором хранится список товаров бакалейной Интернет-лавочки:
2234,Соль йодированная, 2-50, 17
2235,Соль морская, 3-20,2
2236,Соль каменная, 1-70,Продано
3210,Масло растительное,32-00,4
3213,Масло подсолнечное,34-00,Продано
3215,Масло соевое,30-00, Не берут

В результате выполнения приведенной в листинге 10.1 программы вы получите таблицу, приведенную на рис. 10.1.

Рис. 10.1. Список товаров бакалейной лавочки

10.3.6. Считывание очередной строки: fgets

string fgets (int fp, int length)

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

Указатель файла должен быть зарегистрирован в системе и указывать на файл, открытый с помощью fopen () (см. раздел 10.3.10).

В случае обнаружения ошибки функция возвращает false.

совет
       Существует довольно распространенная ошибка при работе с этой функцией: програм- мисты, имеющие опыт работы на Си, используют синтаксис Си-библиотеки, который не совпадает с РНР.

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

$fd = fopen ("/tmp/inputfile.txt", "r");
while (! feof ($fd)) {
       $buffer = fgets($fd, 4096);
       echo $buffer. "<br>";
} fclose ($fd);

См. также описание f read() (раздел 10.3.13), popen() (раздел 10.4.2) и fgetc() (раздел 10.3.4).

10.3.7. Загрузка строки с пропуском HTML: fgetss

string fgetss (int fp, int length [, string allowable_tags] )

Функция работает в целом идентично рассмотренной выше fgets (), но отличается тем, что после загрузки строки производится удаление всех тегов HTML, если таковые в ней присутствуют.

Вы можете также использовать необязательный третий аргумент, чтобы указать теги, которые удалять не следует.

См. также описание fopen() (раздел 10.3.10 ) и рореn() (раздел 10.4.2).

10.3.8. Загрузка всего файла: file

array file (string filename [, int use_include_path])

Функция работает идентично readf ile() (см. раздел 10.5.3) с тем отличием, что fi1е() возвращает запрошенный файл в массиве. При этом каждый элемент массива представляет собой одну строку файла. Символ новой строки является последним символом каждой строки.

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

Вот пример использования этой функции:
<?php
// Извлечь из Сети страничку и распечатать ее
$fcontents = file ('http://www.php.net');/
while (list ($line_num, $line) = each ($fcontents)) {
       echo "<b>Строка $line_num:</b> ";
       echo htmlspecialchars ($line) . "<br>\n";
} // Преобразовать внешнюю страницу в строку
$fcontents = join ('', file ('http://www.php.net'));/
?>

10.3.9. Блокирование доступа к файлу: flock

bool flock (int fp, int operation [, int wouldblock])

PHP-машина поддерживает достаточно переносимый механизм блокирования файлов. Функция flock() работает с указателем fр, который должен указывать на открытый файл. При этом аргумент operation может принимать одно из перечисленных ниже значений:

LOCK_SH Установка совместного блока (shared lock) при открытии файла для чтения
LOCK_EX Установка личного блока (exclusive lock) при открытии файла для записи
LOCK_UN Освобождение как совместного, так и личного блоков
LOCK_NB Запрещение блокировки файла при вызове flock()

Функция f1осk () позволяет вам сформировать простую, но эффективную модель доступа «тяни-толкай» (чтение-запись), которая может использоваться практически на любой вычислительной платформе. Третий, необязательный аргумент устанавливается равным true, если заказанная блокировка должна состояться (см. условие возникновения ошибки EWOULDBLOCK в документации к UNIX).

В случае успешного завершения функция возвращает true, а при ошибке — false. Ошибкой считается невозможность выполнения заказанной пользователем операции.

примечание
       В большинстве операционных систем flock() реализуется на уровне вычислительных про- цессов. Поэтому при использовании многонитевого API-сервера, подобного используемому в ISAPI, вы уже не можете рассчитывать на блокировку с помощью flock(), поскольку другие сценарии РНР работают с параллельными нитями того же экземпляра сервера!

10.3.10. Открытие файла: fopen

int fopen (string filename, string mode [, int use_include_path])

Функция осуществляет открытие локального или удаленного файла и возвращает указатель на него. Указатель используется при всех прочих операциях с содержимым файла. Если имя файла начинается с «http://», производится открытие HTTP-соединения с указанным сервером и возвращается указатель на содержимое соответствующей страницы на сервере. При этом PHP-машина автоматически отправляет заголовок «Host:», если необходимо обслуживать виртуальные серверы, различающиеся по доменным именам.

Если имя запрошенного файла начинается с последовательности «ftp: //», функция инициализирует FTP-соединение с указанным сервером, после чего возвра- щается указатель на запрошенный файл на этом сервере. Если окажется, что FTP- сервер не поддерживает пассивный режим работы, функция fopen () сигнализирует об ошибке и завершает работу. При работе с FTP-сервером вы можете открыть файл как для чтения, так и для записи, но не одновременно в обоих режимах.

Если имя открываемого файла представляет собой одну из конструкций: «php: / / stdin», «php://stdout» или «php://stderr», PHP-машина выполняет открытие соответствующего стандартного канала ввода-вывода.

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

В случае возникновения ошибки функция возвращает false.

Режим открытия файла определяется аргументом mode и может принимать следу- ющие значения:

"r"Файл открывается только для чтения. Указатель файла устанавливается на его начало
"r+"Файл открывается на чтение и на запись. Указатель файла устанавливается в его начало
"w"Файл открывается только для записи. Указатель файла устанавливается на его начало. Все старое содержимое файла теряется, так как счетчик длины файла устанавливается равным 0. Если файл с указанным именем не существует, функция пытается его создать
"w+"Файл открывается на чтение и на запись. Указатель файла устанавливается на его начало. Все старое содержимое файла теряется, так как счетчик длины файла устанавливается равным 0. Если файл с указанным именем не существует, функция пытается его создать
"а"Файл открывается только на запись. Указатель файла помещается в конец файла. Если файл с указанным именем не существует, функция пытается его создать
"а+"Файл открывается только на чтение и на запись. Указатель файла помещается в конец файла. Если файл с указанным именем не существует, функция пытается его создать

совет
       Указатель режима может также дополнительно содержать символ «b». Он используется в операционных системах, где реализованы различные механизмы для работы с текстовыми и двоичными файлами. В UNIX этот модификатор смысла не имеет и игнорируется.

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

Вот несколько примеров открытия файла с помощью fopen ():
$fp = fopen ("/home/rasmus/file. txt", "r");
$fp = fopen ("/home/rasmus/file.gif", "wb");
$fp = fopen ("http://www.php.net/", "r");
$fp = fopen ("ftp://user:password@example.com/", "w");

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

Если же вы, к своему несчастью, пытаетесь пользоваться РНР в среде Windows, вы должны закрывать ESC-последовательностями любые упоминания обратных косых в именах файлов или использовать принятые во всем цивилизованном мире прямые косые в путевых именах:

$fp = fopen ("с:\\data\\info.txt", "r");

10.3.11. Загрузка оставшихся данных: fpassthru

int fpassthru (int fp)

Функция осуществляет считывание из файла всех оставшихся данных и записывает результаты в устройство стандартного вывода. В случае возникновения ошибки функция возвращает false.

Аргумент fр должен представлять собой правильный указатель файла, который указывает на файл, открытый с помощью функций fopen(), popen() или fsockopen(). После завершения работы функции fpassthru() файл автоматически закрывается.

10.3.12. Запись строки в файл: fputs

int fputs (int fp, string str [, int length])

Функция fputs () представляет собой аналог функции fwrite() и полностью ей идентична. Имейте в виду, что последний аргумент является необязательным, и если он отсутствует, то в выходной файл помещается вся строка целиком.

10.3.13. Общая функция чтения из файла: f read

10.3.12. Запись строки в файл: fputs

string fread (int fp, int length)

Функция fread () осуществляет чтение до 1ength байт из файла, адресуемого указателем fp. Чтение прекращается, как только будет считано указанное количество байтов или достигнут конец файла:

// загружаем все содержимео файла в строковую переменную.
// Естественно, исключительно с добрыми намерениями
$filename = "/etc/passwd";
$fd = fopen ($filename, "r");
$contents = fread ($fd, filesize ($filename));
fclose ($fd);

В системах, в которых различается обработка текстовых и двоичных файлов (актаким относится, например, Windows со своей манерой осуществлять дополнительные преобразования CR-LF без уведомления пользователя), файлы должны открываться с дополнительным модификатором «b» (см. раздел 10.3.10):

$filename = "с:\\files\\kartinka.jpg";
$fd = fopen ($filename, "rb");
$contents = fread ($fd, filesize ($filename));
fclose ($fd) ;

10.3.14. Чтение по формату: fscanf

mixed fscanf (int fp, string format [, string varl...])

Функция fsсanf () в целом подобна sscanf(), но в отличие от последней получает входные данные из указанного аргументом f p указателя и уже затем интерпретирует полученные данные в соответствии с форматом. Если функции переданы только два параметра, разобранные по формату значения возвращаются в виде массива. В противном случае результаты разбора передаются указанным переменным varl и т. д., а сама функция возвращает количество сформированных значений. При этом, как и следовало ожидать, дополнительные параметры должны передаваться по ссылке (см. раздел 4.3). Для разбора мы можем использовать следующую программу:

$fp = fopen ("users.txt", "r") ;
while ($userinfo = fscanf ($fp, "%s\t%s\t%s\n")) {
       list ($name, $profession, $countrycode) = $userinfo;
       // обработка разобранных данных
}
fclose($fp):

10.3.15. Перемещение указателя: fseek

int fseek (int fp, int offset [, int whence])

Функция устанавливает указатель файла в позицию, заданную смещением offset. Новая позиция, представляющая собой смещение относительно начала файла, получается путем прибавления смещения к позиции, указанной аргументом whence, который может принимать следующие значения:

SEEK_SET Устанавливает позицию файла равную заданному смещению от начала файла
SEE K_CURУстанавливает указатель в позицию текущее_положение + смещение
SEEK_END Устанавливает указатель на конец файла + смещение
По умолчанию используется значение SEEK_SET.

При успешном завершении функция возвращает 0, а при ошибке - -1. При этом, в полном соответствии с особенностями функций файловой системы UNIX, перемещение за границу конца файла ошибкой не является.

Функция может применяться только к локальным файлам.

10.3.16. Информация о файле: fstat

array fstat (int fp)

Функция собирает информацию о файле, адресуемом указателем fр. В целом эта функция аналогична stat () (см. раздел 10.5.5), но работает не с именем файла, а с его указателем.

Возвращает массив, содержащий данные о файле, помещенные в элементы с индексами:
1. Устройство.
2. Inode.
3. Количество ссылок.
4. UID владельца файла.
5. GID владельца файла.
6. Тип устройства.
7. Размер файла в байтах.
8. Время последнего доступа к файлу (по чтению).
9. Время последней модификации (по записи).
10. Время последнего изменения параметров.
11. Размер блока.
12. Количество выделенных блоков.

10.3.17. Текущая позиция указателя: ftell

int ftell (int fp)

Функция возвращает текущее положение указателя, адресуемого через fр, то есть текущее смещение в потоке данных. В случае возникновения ошибки функция возвращает false.

10.3.18. Обрезка файла: ftruncate

int ftruncate (int fp, int size)

Функция осуществляет обрезку файла, заданного указателем f р, до указанного размера size. В случае успеха функция возвращает true, при ошибке — false.

10.3.19. Запись данных в файл: fwrite

int fwrite (intfp., string string [, int length])

Функция fwrite () производит запись содержимого строки string в файл, адресуемый указателем fp. Если задан аргумент length, операция записи прекращается после вывода указанного количества символов либо при достижении конца строки.

10.3.20. Назначение буфера: set_file_buffer

int set_file_buffer (int fp, int buffer)

Как правило, вывод данных с помощью функции fwrite () осуществляется через буферы размером 8 Кбайт. Это означает, что если в один и тот же поток (файл) пытаются вывести данные два процесса, каждый из них приостанавливается после заполнения 8-килобайтного блока, чтобы предоставить возможность вывода другому. Функция set_file_buffer () устанавливает номер и размер буфера для файла, адресуемого указателем f р. Если новое значение равно 0, операции записи выполняются без буферизации. В этом случае вы может быть уверены, что все вызовы fwrite() (см.раздел 10.3.19)будут действительно завершены до попыток других процессов выполнить запись в этот же выходной поток.

Функция возвращает 0 в случае успешного завершения или EOF, если запрос неприменим к данному файлу.

Вот пример создания небуферированного потока:
$fp=fopen($file, "w");
if($fp){
       set_file_buffer($fp, 0);
       fputs($fp, $output);
       fclose($fp);
}

10.3.21. Возвращение указателя файла в начало:rewind

int rewind (int fp)

Устанавливает указатель файла f p на начало. В случае возникновения ошибки возвращает false. Указатель f p должен представлять собой результат выполнения функции fopen(). См. также описание fseek () (раздел 10.3.15) и f tell () (раздел 10.3.17).

10.3.22. Обновление даты модификации файла:touch

int touch (string filename [, int time])

Пытается установить временную метку модификации содержимого файла, заданного именем filename, назначение, указанное аргументом time. Если данный аргумент не используется, присваивается метка, соответствующая текущему времени.

Если файл с данным именем не существует, он будет автоматически создан. В случае успешного завершения функция возвращает true, а при ошибке — false.

Вот пример использования этой функции:
if (touch ($FileName)) {
       print "Время модификации файла $FileName".
           "приведено к текущему времени";
} else {
       print "Изменить время модификации $FileName не удалось!";

назад
далее

Сайт управляется системой uCoz