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


Содержание

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

В PHP существует богатый функционал по управлению файлами. Из этой статьи вы узнаете про:

  • — базовые операции управления файлами (создание, чтение, запись) с помощью функций fopen() , fclose() , fgets() , fwrite()
  • — более удобное управление благодаря функциям file() , file_get_contents() и file_put_contents()
  • — удаление, копирование и перенос файлов

Работа с файлом с помощью fopen()

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

Итак, с помощью функции fopen() мы можем открыть файл (а может и создать, если нужно):

Функция fopen() возвращает так называемый указатель на файл, он понадобится нам для использования других функций. Кстати, тип данных этого дескриптора — resource , наконец-то мы с ним встретились. Обычно этот тип используется для работы с файлами и базами данных.

Первым параметром мы передаём ссылку на файл, вторым — модификатор доступа к файлу. Ниже перечислены наиболее популярные модификаторы:

  • r — открытие для чтения, указатель переходит в начало файла.
  • r+ — открытие для чтения и записи, указатель переходит в начало файла.
  • w — открытие для записи, указатель переходит в начало файла. Если файла нет — создаётся, если есть — очищается от данных.
  • w+ — открытие для чтения и записи, в остальном аналогичен w .
  • a — открытие для записи, указатель переходит в конец файла. Если файла нет — создаётся.
  • a+ — открытие для чтения и записи, в остальном аналогичен a .
  • x — создание и открытие для записи, указатель переходит в начало файла. Если файл существует — PHP покажет ошибку.
  • x+ — создание и открытие для чтения и записи, в остальном аналогичен x .

Указатель — это нечто вроде курсора. Вы можете переместить его в любое место файла, чтобы добавить или отредактировать определённые данные.

Для записи данных в файл существует функция fwrite() . Давайте попробуем создать файл и записать в него какие-нибудь данные:

Заметьте, из-за модификатора w при каждом запуске скрипта данные в файле стираются и добавляются заново. Если модификатор заменить на a , данные будут не перезаписываться, а добавляться в конец файла.

Для построчного чтения файла используется функция fgets() :

При каждом запуске fgets получает следующую строку и возвращает её в $line . Вторым параметром передаётся максимальная длина строки. Это означает, что если строка слишком длинная, она будет обрезана.

Удобная работа с файлами

Все эти модификаторы, дескрипторы, куча лишних функций, sick! Предлагаю забыть об этом как о страшном сне и познакомиться с более удобными инструментами.

Получить содержимое файла в виде строки можно с помощью функции file_get_contents() :

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

Для создания файла, а также записи строки в файл есть функция file_put_contents() . Первым параметром передаём ссылку на файл, вторым — данные. По-умолчанию функция перезапишет информацию в файле, но если 3-им параметром передать константу FILE_APPEND , данные будут добавлены в конец файла:

Чтобы записать массив в файл, мы можем просто передать его 2-ым параметром, но тогда данные запишутся подряд без каких-либо разграничительных символов. Поэтому лучше сначала превратить массив в строку, добавив переносы строк «\n» в качестве разделителей:

Удаление, копирование и перенос файлов

Для удаления файлов используется функция unlink() :

Чтобы скопировать файл, используем функцию с говорящим названием copy() :

Для переноса и переименования файла используется функция rename() :

ГЛАВА 7 Файловый ввод/вывод и файловая система

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

Проверка существования и размера файла

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

file_exists( ) и is_file( ).

Функция f ilе_ехists ( ) проверяет, существует ли заданный файл. Если файл существует, функция возвращает TRUE, в противном случае возвращается FALSE. Синтаксис функции file_exists( ):

bool file_exists(string файл)

Пример проверки существования файла:

if (! file_exists ($filename)) :

print «File $filename does not exist!»;

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

bool is_file(string файл)

Следующий пример показывает, как убедиться в существовании файла и возможности выполнения операций с ним:

print «The file $file is valid and exists!»;

print «The file $file does not exist or it is not a valid file!»;

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

Функция filesize( ) возвращает размер (в байтах) файла с заданным именем или FALSE в случае ошибки. Синтаксис функции filesize( ):

int filesize(string имя_файла)

Предположим, вы хотите определить размер файла pastry.txt. Для получения нужной информации можно воспользоваться функцией filesize( ):

$fs = filesize(«pastry.txt»); print «Pastry.txt is $fs bytes.»;

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

Pastry.txt is 179 bytes.

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

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

Прежде чем выполнять операции ввода/вывода с файлом, необходимо открыть его функцией fopen( ).

Функция fopen( ) открывает файл (если он существует) и возвращает целое число — так называемый файловый манипулятор (file handle). Синтаксис функции fopen( ):

int fopen (string файл, string режим [, int включение_пути])

Открываемый файл может находиться в локальной файловой системе, существовать в виде стандартного потока ввода/вывода или представлять файл в удаленной системе, принимаемой средствами HTTP или FTP.

Параметр файл может задаваться в нескольких формах, перечисленных ниже:

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

Если параметр задан в виде php://stdin, php://stdout или php://stderr, открывается соответствующий стандартный поток ввода/вывода.

Если параметр начинается с префикса http://, функция открывает подключение HTTP к серверу и возвращает манипулятор для указанного файла.

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

При работе в пассивном режиме сервер ЯР ожидает подключения со стороны клиентов. При работе в активном режиме сервер сам устанавливает соединение с клиентом. По умолчанию обычно используется активный режим.

Параметр режим определяет возможность выполнения чтения и записи в файл. В табл. 7.1 перечислены некоторые значения, определяющие режим открытия файла.

Таблица 7.1. Режимы открытия файла

Режим Описание
Только чтение. Указатель текущей позиции устанавливается в начало файла
r+ Чтение и запись. Указатель текущей позиции устанавливается в начало файла
w Только запись. Указатель текущей позиции устанавливается в начало файла, а все содержимое файла уничтожается. Если файл не существует, функция пытается создать его
w+ Чтение и запись. Указатель текущей позиции устанавливается в начало файла, а все содержимое файла уничтожается. Если файл не существует, функция пытается создать его
a Только запись. Указатель текущей позиции устанавливается в конец файла. Если файл не существует, функция пытается создать его
a+ Чтение и запись. Указатель текущей позиции устанавливается в конец файла. Если файл не существует, функция пытается создать его

Если необязательный третий параметр включение_пути равен 1, то путь к файлу определяется по отношению к каталогу включаемых файлов, указанному в файле php.ini (см. главу 1).

Ниже приведен пример открытия файла функцией fopen( ). Вызов die( ), используемый в сочетании с fopen( ), обеспечивает вывод сообщения об ошибке в том случае, если открыть файл не удастся:

$file = «userdata.txt»; // Некоторый файл

$fh = fopen($file, «a+») or die(«File ($file) does not exist!»);

Следующий фрагмент открывает подключение к сайту PHP (http://www.php.net):

$site = «http://www.php.net»: // Сервер, доступный через HTTP

$sh = fopen($site., «r»); //Связать манипулятор с индексной страницей Php.net

После завершения работы файл всегда следует закрывать функцией fclose( ).

Функция fclose( ) закрывает файл с заданным манипулятором. При успешном закрытии возвращается TRUE, при неудаче — FALSE. Синтаксис функции fclose( ):

int fclose(int манипулятор)

Функция fclose( ) успешно закрывает только те файлы, которые были ранее открыты функциями fopen( ) или fsockopen( ). Пример закрытия файла:

$fh = fopen($file, «r»);

// Выполнить операции с файлом

print «File Sfile does not exist!»;

Запись в файл

С открытыми файлами выполняются две основные операции — чтение и запись.

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

bool is_writeable (string файл)

Одно важное обстоятельство: скорее всего, PHP будет работать под идентификатором пользователя, используемым web-сервером (как правило, «nobody»). Пример использования is_writeable( ) приведен в описании функции fwrite( ).

Функция fwrite( ) записывает содержимое строковой переменной в файл, заданный файловым манипулятором. Синтаксис функции fwrite( ):

int fwrite(int манипулятор, string переменная [, int длина])

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

Функция fputs( ) является псевдонимом fwrite( ) и может использоваться всюду, где используется fwrite( ).

Функция fputs( ) является псевдонимом fwrite( ) и имеет точно такой же синтаксис. Синтаксис функции fputs( ):

int fputs(int манипулятор, string переменная [, int длина])

Лично я предпочитаю использовать fputs( ). Следует помнить, что это всего лишь вопрос стиля, никак не связанный с какими-либо различиями между двумя функциями.

Чтение из файла

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

Функция i s_readable( ) позволяет убедиться в том, что файл существует и для него разрешена операция чтения. Возможность чтения проверяется как для файла, так и для каталога. Синтаксис функции is_readable( ):

boo! is_readable (string файл]

Скорее всего, PHP будет работать под идентификатором пользователя, используемым web-сервером (как правило, «nobody»), поэтому для того чтобы функция is_readable( ) возвращала TRUE, чтение из файла должно быть разрешено всем желающим. Следующий пример показывает, как убедиться в том, что файл существует и доступен для чтения:

// Открыть файл и установить указатель текущей позиции в конец файла

$fh = fopen($filename, «r»);

print «$filename is not readable!»;

Функция fread( ) читает из файла, заданного файловым манипулятором, заданное количество байт. Синтаксис функции fwrite( ):

int fread(int манипулятор, int длина)

Манипулятор должен ссылаться на открытый файл, доступный для чтения (см. описание функции is_readable( )). Чтение прекращается после прочтения заданного количества байт или при достижении конца файла. Рассмотрим текстовый файл pastry.txt, приведенный в листинге 7.1. Чтение и вывод этого файла в браузере осуществляется следующим фрагментом:

$fh = fopen(‘pastry.txt’, «r») or die(«Can’t open file!»);

$file = fread($fh, filesize($fh));

Используя функцию fllesize( ) для определения размера pastry.txt в байтах, вы гарантируете, что функция fread( ) прочитает все содержимое файла.

Листинг 7.1. Текстовый файл pastry.txt

Recipe: Pastry Dough

1 1/4 cups all-purpose flour

3/4 stick (6 tablespoons) unsalted butter, chopped

2 tablespoons vegetable shortening 1/4 teaspoon salt

3 tablespoons water

Функция fgetc( ) возвращает строку, содержащую один символ из файла в текущей позиции указателя, или FALSE при достижении конца файла. Синтаксис функции fgetc( ):

string fgetc (int манипулятор)

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

$fh = fopen(«pastry.txt», «r»); while (! feof($fh)) :

print $char; endwhile;

Функция fgets( ) возвращает строку, прочитанную от текущей позиции указателя в файле, определяемом файловым манипулятором. Файловый указатель должен ссылаться на открытый файл, доступный для чтения (см. описание функции is_readable( ) ранее в этой главе). Синтаксис функции fgets( ):

string fgets (int манипулятор, int длина)

Чтение прекращается при выполнении одного из следующих условий:

  • из файла прочитано длина — 1 байт;
  • из файла прочитан символ новой строки (включается в возвращаемую строку);
  • из файла прочитан признак конца файла (EOF).

Если вы хотите организовать построчное чтение файла, передайте во втором параметре значение, заведомо превышающее количество байт в строке. Пример построчного чтения и вывода файла:

$fh = fopen(«pastry.txt», «r»);

$line = fgets($fh, 4096);

Функция fgetss( ) полностью аналогична fgets( ) за одним исключением — она пытается удалять из прочитанного текста все теги HTML и PHP:

string fgetss (Int манипулятор, int длина [, string разрешенные_теги])

Прежде чем переходить к примерам, ознакомьтесь с содержимым листинга 7.2 — этот файл используется в листингах 7.3 и 7.4.

Листинг 7.2. Файл science.html

Breaking News — Science

Alien lifeform discovered

Early this morning, a strange new form of fungus was found growing in the closet of W. J. Gilmore’s old apartment refrigerator. It is not known if powerful radiation emanating from the tenant’s computer monitor aided in this evolution.

Работа с файлами и директориями в PHP

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

Получить имя файла из URL

Имя файла без расширения

Получить расширение файла

Размер файла

Чтобы получить размер файла применяется функция filesize($filename) , которая возвращает размер файла указанного в $filename в байтах.

Размер директории

Функция рекурсивно проходит по всем директориям и возвращает размер всех файлов в байтах.

Конвертация байтов в килобайты и мегабайты

Чтобы конвертировать байты в килобайты и мегабайты можно применить следующую функцию:

Получить список файлов директории в виде массива

То же самое делает функция scandir() , разница в том что у нее в массиве будут « . », « .. » и есть возможность сортировки.

Безопасное сохранение файла

Чтобы не затереть существующий файл на сервере можно применить данную функцию.

В функцию передаётся путь и имя файла, если на сервере уже существует такой файл, функция к концу файла приписывает префикс. Также если директория не существует, пытается её создать.

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

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

Как создать новый файл и записать в него что-то?

Как прочитать содержимое текстового файла целиком?
1 способ.

Как прочитать содержимое текстового файла построчно?

Как добавить информацию в начало файла?

Как удалить строчку из файла?

Для удаления первой или последней строчки воспользуйтесь функциями: array_shift(); и array_push();, вместо array_splice(); .

Как послать файл пользователю?

Как получить массив файлов в каталоге с определенным расширением?

Как вывести случайную строку из файла?
Обычно такой вопрос задаются те, кто не использует какой-нибудь Базы Данных, тем не менее нуждается в ее функциях.
Вывести случайною строку из файла, например случайный анекдот можно так:

Функция rand(); получает два параметра: первый — 0, второй — количество элементов массива минус 1. Т.е. устанавливается диапазон выбора (минимум — максимум).

Как записать файл в определенной кодировке?

Как скопировать / переименовать / удалить файл или директорию?

Что такое права доступа ( CHMOD ) и как их изменить?
Права доступа показывают, какие операции (чтение, запись, выполнение) с файлом (директорией) может выполнять пользователь.
Права доступа определяются для 3 пользователей:
1. Хозяина (создавшего файл).
2. Группы, в которую входит хозяин файла.
3. Остальные пользователи.
Права доступа могут быть записанны как в буквенном, так и в символьном варианте.
В буквенном: drwxr-x-r-x (стандартные права для директорий).
Первый символ — специальный, показывающий чем этот файл является (в UNIX системах все представленно ввиде файлов, даже директории). d — директория.
Затем идут три комбинации, rwx — права для хоязина, r-x — права для группы, r-x — права доступа для отсальных пользователей.
r — пользователь имеет право чтения файла (по сути просто обратиться к нему).
w — пользователь имеет право записать / перезаписать файл.
x- показывает, что файл может быть исполнен (актуально для CGI сценариев).
В числовом варианте права каждого пользователя определяет цифра, которая складывается из суммы:
r — 4, w — 2, x -1. Таким образом drwxr-xr-x — 755.
Изменить права доступа можно либо с помощь FTP клиента, либо через shell.
С помощью PHP права доступа меняются функцией chmod().

В Операционных Системах Windows права доступа всегда 777.
Какую можно получить информацию о файле?
Информацию о файле можно получить с помощью функции:

Выведет массив, где:
0 — dev — устройство
1 — ino — inode — отедьная функция: fileinode();
2 — mode — inode protection mode
3 — nlink — number of links
4 — uid — идентификатор хоязина — отедьная функция: fileowner();
5 — gid — идентификатор группы — отедьная функция: filegroup();
6 — rdev — device type, if inode device *
7 — size — размер — отедьная функция: filesize();
8 — atime — время последнего доступа к файлу (Unix time) — отедьная функция: fileatime();
9 — mtime — время последней модификации файла (Unix time) — отедьная функция: filemtime();
10 — ctime — время создания файла (Unix time) — отедьная функция: filectime();
11 — blksize — blocksize of filesystem IO *
12 — blocks — number of blocks allocated
Аналогом данной функции является fstat(), но работает она с открытым указателем.
Как организовать файл INI и его парсинг (чтение и запись)?
В PHP существует возможность парсинга *.ini файлов, которые имеют тот же синтаксис, что и php.ini, т.е.:
[категория]
= ;

Для этого есть функция: parse_ini_file();

Если вы устанавливаете второй параметр — FALSE (или не укажите вовсе), то вы получите массив всех ключей и значений. Если укажите TRUE, то получите многомерный массив, где верхними элементами будут название категорий.
Обращаем ваше внимание, что *.ini файл по умолчанию воспринимается веб-сервером, как текстовый документ, поэтому не рекомендуем хранить в нем важные данные.
ВАЖНО: значение не состоящие из символов латинского алфавита или цифр должны быть заключены в кавычки.
Настоятельно не рекомендуем вам использовать не латинские символы.
Запись файла *.ini вам придется производить собственным алгоритмом.

Данные алгоритм не осуществляет проверку на не латинские символы и не производит их обрамление кавычками.

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

Как узнать сколько места занимает на диске каталог?
Размер папки складывается из суммы размеров файлов внутри не и папок.

Как отредактировать определенную строчку в файле?

Как «обнулить» (очистить) содержимое файла?

Как посчитать количество файлов в папке и подпапках?

Как проверить на существование удаленный файл?

Как узнать размер удаленного файла?

Работа с файлами в PHP.

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

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

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

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

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

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

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

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

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

Конструкция or die(). Вот примеры:

Обратите внимание на конструкцию or die(). Конструкцию or die() удобно применять при работе с файлами. Оператор or аналогичен ||, но имеет очень низкий приоритет (даже ниже, чем у =), поэтому всегда выполняется уже после присваивания. Поэтому первый пример с точки зрения РНР выглядит так:

Если файл открыть не удалось, fopen() возвращает false, и осуществляется вызов die(). Тут нельзя просто так заменить or на, казалось бы, равнозначный ему оператор ||, потому что последний имеет гораздо более высокий приоритет — выше, чем у =. Поэтому в результате вызова функции:

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

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

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

При открывании FTP-файла можно производить либо запись, либо читать из него, но никак то и другое одновременно. Кроме того, FTP-сервер должен поддерживать пассивный режим передачи. Не забывайте указывать имя пользователя и пароль.

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

Иногда приходится работать с временными файлами, которые при завершении программы надо бы удалить. При этом интересен лишь файловый дескриптор, а не имя временного файла. Для создания безымянных временных файлов в РНР предусмотрена специальная функция:

Создает новый файл с уникальным именем и открывает его на чтение и запись. В дальнейшем вся работа должна вестись с возвращенным файловым дескриптором, потому что имя файла недоступно. Как такое может произойти? В большинстве систем после открытия файла его имя можно спокойно удалить из дерева файловой системы, продолжая при этом работать с «безымянным» файлом через дескриптор, как обычно. При закрытии этого дескриптора блоки, которые занимает файл на диске, будут автоматически помечены как свободные. Пространство, занимаемое временным файлом, автоматически освобождается при его закрытии и при завершении работы программы. После работы файл лучше всего закрыть. На самом деле это делается и автоматически при завершении сценария программы, но лучше самому закрыть. Особенно если открываете десятки ( или сотни) файлов в цикле:

Закрывает файл, открытый предварительно функцией fopen() или рореn(), или fsockopen(). Возвращает false, если файл закрыть не удалось( что-то с ним случилось или же разорвалась связь с удаленным хостом).В противном случае возвращает значение «истина». Вы должны всегда закрывать FTP- и HTTP-соединения, потому что в противном случае «ничьей» файл приведет к неоправданному простою канала и излишней загрузке сервера. Тем более успешно закрыв соединение, будете уверены в том, что все данные были доставлены без ошибок.

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

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

Функция string fread(int $f, int $numbytes) читает из файла $f блок из $numbytes символов и возвращает строку этих символов. После чтения указатель файла продвигается к следующим после прочитанного блока позициям и это происходит для всех остальных функций. Если $numbytes больше, чем можно прочитать из файла, возвращается что удалось считать. Этот прием можно использовать, если нужно считать в строку файл целиком и задайте в $numbytes очень большое число — пусть сто тысяч. Но если Вам надо сэкономить память в системе, то так поступать не стоит, потому что в некоторых версиях РНР передача большой длины строки во втором параметре fread() вызывает первоначальное выделение памяти в соответствии с запросом:

Записывает в файл $f все содержимое строки $st. Эта функция составляет пару для fread(), действуя в противоположном напрвлении.

Когда указан символ t в режиме открытия файла все \n автоматически преобразуются в тот разделитель строк, который принят в операционной системе.

С помощью описанных двух функций можно копировать файлы: считывать файл целиком посредством fread() и затем записывать данные в новое место при помощи fwrite(). В языке РНР-кодов есть отдельная функция — сору().

Читает из файла одну строку, заканчивающуюся символом новой строки \n. Этот символ считывается и включается в результат функции. Если строка в файле занимает больше $length-l байтов, то возвращаются только ее $length-1 символов. Функция string fgets (int $f, int $ length) полезна тогда. когда открыли файл и хотите проверить все его строки. Однако даже в этом случае лучше (и быстрее) будет воспользоваться функцией file(). Функция fgets(), как и функция fread(), в случае текстового режима в Windows заботится о преобразовании пар \r\n в один символ \n, так что будьте внимательны при работе с текстовыми файлами в операционной системе Windows:

Эта функция — синоним для fwritet().

Чтение CSV-файла. Программа Excel Microsoft Office стала настолько популярной, что в РНР встроили функцию для работы с одним из форматов файлов, в которых может сохранять данные Excel. Функция довольно удобна и экономит пару несколько строк дополнительного кода:

Функция читает одну строку из файла, заданного дескриптором $f, и разбивает ее по символу $delim. Поля CSV-файла могут быть ограничены кавычками — символ кавычки задается в четвертом параметре $quote. Параметры $delim и $quote должны обязательно быть строкой из одного символа, в противном случае принимается во внимание только первый символ этой строки. Параметр $length задает максимальную длину строки как это делается в функции fgets(). Функция возвращает получившийся список полей или false, если строки кончились. Хотя в документации сказано, что пустые строки в файле не игнорируются, а возвращаются как список из одного элемента NULL, хотя это не совсем так.

Функция fgetcsv() гораздо более универсальна, чем просто пара fgets()/explode(). Функция fgetcsv() может работать с CSV-файлами, в чьих записях встречается перевод новой строки.

Положение указателя текущей позиции:

Возвращает true, если достигнут конец файла, т.е. если указатель файла установлен за концом файла. Функция int feof (int $f) используется так:

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

Устанавливает указатель файла на байт со смещением $offset от начала файла, от его конца или от текущей позиции, в зависимости от параметра $whence. Это выражение может не сработать, если дескриптор $f соединен не с обычным локальным файлом, а с соединением HTTP или FTP.

Параметр $whence задает смещение $offset. В языке РНР для задания смещение $offset существуют три константы, равные, соответственно, 0, 1 и 2:

— SEEK_SET — устанавливает позицию, начиная с начала файла;

— SEEK_CUR — отсчитывает позицию относительно текущей позиции;

— SEEK END — отсчитывает позицию относительно конца файла.

В случае использования последних двух констант параметр $offset вполне может быть отрицательным. Будьте внимательны при использовании SEEK_END параметр $offset в большинстве случаев должен быть отрицательным, если только Вы не собираетесь писать за концом файла, при этом размер файла будет автоматически увеличен. При успешном завершения функция возвращает 0, а в случае неудачи -1.

Возвращает позицию указателя файла. Вы можете сохранить текущее положение в переменной, выполнить с файлом какие-то операции, а потом вернуться к старой позиции при помощи функции fseek().

усекает открытый файл $f до размера Snewsize. Файл должен быть открыт в режиме, разрешающем запись. Следующий код очищает весь файл:

Будьте осторожны при применении функции ftruncate(). Можете очистить файл, в то время как текущая позиция дескриптора останется указывать на уже удаленные данные. При попытке записи по такой позиции ничего страшного не произойдет, просто образовавшаяся «пустота» будет заполнена байтами с нулевыми значениями. Не забывайте сразу же после ftruncate() вызывать fseek(), чтобы передвинуть файловый указатель внутрь файла.

Работа с путями. Иногда приходится манипулировать именами файлов. Допустим, прицепить к имени слева путь к какому-то каталогу или, наоборот, из полной спецификации файла выделить его непосредственное имя. В РНР для работы с именами файлов введены несколько функций.

Функция basename() не проверяет существование файла. Функция basename() берет часть строки после самого правого слэша и возвращает ее. Функция basename() правильно обрабатывает как прямые, так и обратные слэши под Windows.

если функции dirname() передать «чистое» имя файла, она вернет «.», что означает «текущий каталог».

генерирует имя файла в каталоге $dir с префиксом Sprefix в имени, чтобы созданный под этим именем в будущем файл был уникален. Для этого к строке $prefix присоединяется некое случайное число. Например, вызов tempnam(«/tmp», «temp») может возвратить эдакое /tmp/temp3a6b243c. Если такое имя нужно создать в текущем каталоге, передайте $dir=».». Если каталог $dir не указан или не существует, то функция возьмет вместо него имя временного каталога из настроек пользователя — обычно хранится в переменной окружения ТМР или TMPDIR. Помимо генерации имени функция создает пустой файл с этим именем. Вот, использовать tempnam() в следующем случае опасно:

хотя функция и возвращает уникальное имя, все-таки существует вероятность, что между tempnam(0 и fopen() «вклинится» какой-нибудь другой процесс, в котором функция tempnam() сгенерировала идентичное имя файла. Такая вероятность очень мала, но все-таки она существует.

Для решения проблемы можете использовать идентификатор текущего процесса РНР, доступный через вызов функции getmypid(), в качестве суффикса имени файла:

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

возложена непростая задача: преобразовать относительный путь в $path в абсолютный, т.е. начинающийся от корня. Например:

К сожалению, последний оператор в некоторых версиях РНР выводит не тот же самый результат, что и функция getcwd(). А именно, к имени текущего каталога «прицепляются» слэши, а иногда даже и /./. Так что, если без определения текущего каталога вам не обойтись, используйте getcwd().

Файл, который указывается в параметре $path, должен существовать, иначе функция возвращает false. Функция realpath() всегда возвращает абсолютное каноническое имя, состоящее только из имен файлов и каталогов — но не имен ссылок.

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

копирует файл с именем $src в файл с именем $dst. При этом, если файл $dst на момент вызова существовал, осуществляется его перезапись. Функция возвращает true, если копирование прошло успешно, а в случае провала — false.

переименовывает или перемещает файл с именем $oldname в файл с именем $newname. Если файл $newname уже существует, регистрируется ошибка, и функция возвращает false. То же происходит и при прочих неудачах. Если же все прошло успешно, возвращается true.

Функция не выполняет переименование файла, если его новое имя расположено в другой файловой системе, на другой смонтированной системе в Unix или на другом диске в Windows. Так что никогда не используйте rename() для получения загруженного по http файла — ведь временный каталог /tmp хостинг-провайдера скорее всего располагается на отдельном разделе диска.

удаляет файл с именем $filename. В случае неудачи возвращает false, иначе — true. На самом деле файл удаляется только, если число «жестких» ссылок на него стало равным 0.

Чтение и запись целого файла.

Считывает файл с именем $filename целиком в бинарном режиме и возвращает массив-список, каждый элемент которого соответствует строке в прочитанном файле. Функция list file(string $filename, bool $use_include_path=false) работает очень быстро — гораздо быстрее, чем если бы использовали fopen() и читали файл по одной строке. Если параметр $use_inciude_path содержит истинное значение, а переданное имя файла — относительное, функция также проводит поиск в каталогах библиотек РНР. Пути к таким каталогам содержатся в переменной inciude_path файла plip.ini И могут быть получены В программе при помощи ini_get(«include_path»). Неудобство этой функции в том, что символы конца строки (обычно \n) не вырезаются из строк файла, а также не транслируются, как это делается для текстовых файлов, так как используется бинарный режим чтения. Конечно, можно потом пройтись по массиву и вручную выполнить trim() для каждого его элемента. Оказывается, есть значительно более быстрый способ добиться того же результата:

эти две строчки не только поместят в массив $lines все строки файла, но еще и:

— удалят лишние символы перевода строки (\n);

— удалят символы \r (за счет режима открытия файла «rt»);

— сделают это быстрее, чем сработала бы функция file().

Пара fread()+explode() работает быстрее, чем один вызов функции file():

Данная функция позволяет в одно действие записать данные $data в файл, имя которого передано в параметре $filename. При этом данные записываются, как есть — трансляция переводов строк не производится. Можете воспользоваться следующими операторами для копирования файла:

Параметр $flags может содержать значение, полученное как сумма следующих констант:

— FILE APPEND — произвести дописывание в конец файла;

— FILE_USE_INCLUDE_PATH — найти файл в путях поиска библиотек, используемых функциями include и require.Применяйте аккуратно, чтобы не стереть важные файлы!.

Функция открывает файл и ищет в нем все теги до тех пор, пока не встретится закрывающий тег . Если очередной тег имеет вид:

то пара названне=>содержимое добавляется в результирующий массив, который под конец и возвращается. Функцию удобно использовать для быстрого получения всех метатегов из указанного файла, потому что работает гораздо быстрее, чем соответствующее использование fopen() и затем чтение и разбор файла по строкам. Если необязательный параметр $use_include_path установлен, то поиск файла осуществляется не только в текущем каталоге, но и во всех тех, которые назначены для поиска инструкциями include, require.

В языке РНР-кодов существует удобная функция, которая позволяет использовать в программах стандартный формат ini-файлов, пришедший из Windows. INI-файл — текстовый файл, с расширением .ini, состоящий из нескольких секций. В каждой секции может быть определено 0 или более пар ключ=>значение.

В файле с расширением .ini можно задавать комментарии двух видов: предваренные символом ; или символами //. При чтении ini-файла они будут проигнорированы.

читает ini-файл, имя которого передано в параметре $filename, и возвращает ассоциативный массив, содержащий ключи и значения. Если аргумент $useSections имеет значение false, тогда все секции в файле игнорируются, и возвращается просто массив ключей и значений. Если же он равен true, тогда функция вернет двумерный массив. Ключи первого измерения — имена секций, а второго измерения — имена параметров внутри секций. Доступ к значению некоторого параметра нужно организовывать так:

заставляет PHP немедленно записать на диск все изменения, которые производились до этого с открытым файлом $f. Что это за изменения? Дело в том, что для повышения производительности все операции записи в файл буферизируются: например, вызов fputs($f, «Это строка!») не приводит к непосредственной записи данных на диск — сначала они попадают во внутренний буфер ( обычно размером 8 Кбайт). Как только буфер заполняется, его содержимое отправляется на диск, а сам он очищается, и все повторяется вновь. Особенный выигрыш от буферизации порциями.

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

устанавливает размер буфера для указанного открытого файла $f. Чаще всего она используется так:

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

Буферизированный ввод/вывод придуман не зря. Не отключайте его без крайней надобности — это может нанести серьезный ущерб производительности. В крайнем случае используйте fflush().

Блокирование файла. При интенсивном обмене данными с файлами в мультизадачных операционных системах встает вопрос синхронизации операций чтения/записи между процессами. Допустим, есть несколько «процессов-писателей» и один «процесс-читатель». Необходимо, чтобы в единицу времени к файлу имел доступ лишь один процесс-писатель, а остальные на этот момент времени как бы «подвисали», ожидая своей очереди. Это нужно, чтобы данные от нескольких процессов не перемешивались в файле, а следовали блок за блоком.

Рекомендательная и жесткая блокировки. На помощь приходит функция fiock(), которая устанавливает так называемую «рекомендательную блокировку» (advisory locking) для файла. Это означает, что блокирование доступа осуществляется не на уровне ядра системы, а на уровне программы. Процессы, которые ею пользуются, будут работать с разделяемым файлом правильно, а остальные. как-нибудь да будут, пока что-нибудь да не случится( как при работе с светофором). С другой стороны, «жесткая блокировка» (mandatory locking; точный перевод — «принудительная блокировка») подобна шлагбауму: никто не сможет проехать, пока его не поднимут. Windows-версия РНР поддерживает только жесткую блокировку.

Функция flock() ведет себя так, как будто бы устанавливается не рекомендательная, а жесткая блокировка. Всегда старайтесь действовать так, чтобы скрипт работал и в условиях рекомендательных, и в условиях жестких блокировок. Единственная функция, которая занимается управлением блокировками в РНР, называется flock():

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

— LOCK SH (или 1) — разделяемая блокировка;

— LOCK EX (или 2) — исключительная блокировка;

— LOCK UN (или з) — снять блокировку;

— LOCK NB (или 4) — эту константу нужно прибавить к одной из предыдущих, чтобы программа не «подвисала» на flock() в ожидании своей очереди, а сразу возвращала управление.


В случае если был затребован режим без ожидания, и блокировка не была успешно установлена, в необязательный параметр-переменную $wouldblock будет записано значение true. При ошибке функция, как всегда, возвращает false, а в случае успешного завершения — true. При работе с файловой системой FAT32, используемой иногда в Windows, функция всегда возвращает индикатор провала, независимо от того, правильно она вызывается или нет.

Исключительная блокировка. Вспомним о процессах-писателей. Каждый такой процесс страстно желает, чтобы в некоторый момент, когда он уже почти готов начать писать, был бы единственным, кому разрешена запись в файл. Он хочет стать исключительным. Отсюда и название блокировки, которую процесс должен для себя установить. Вызвав функцию flock($f, LOCK EX), он может быть абсолютно уверен, что все остальные процессы не начнут без разрешения писать в файл, соответствующий дескриптору $f, пока не выполнит все свои действия и не вызовет flock($f, LOCK UN) или не закроет файл. Если в данный момент процесс — не единственный претендент на запись, операционная система просто не выпустит его из «внутренностей» функции flock(), т.е. не допустит его продолжения, пока процесс-писатель не станет единственным. Момент, когда процесс, использующий исключительную блокировку, становится активным, знаменателен еще и тем, что все остальные процессы-писатели ожидают функцию flock(). Когда закончит свою работу с файлом операционная система выберет следующий исключительный процесс, и т.д..

Как должен быть устроен процесс-писатель, желающий установить для себя исключительную блокировку:

Главное коварство блокировок в том, что с ними очень легко ошибиться. Вот и данный вариант кода является чуть ли не единственным по-настоящему рабочим. Шаг влево, шаг вправо — и все, блокировка окажется неправильной. При открытии файла написали не деструктивный режим w, который удаляет файл, если он существовал, но более терпимый режим — r+, потому что удаление файла есть изменение его содержимого. Что не должны делать до получения исключительной блокировки.

Открытие файла в режиме w и последующий вызов функции flock() — очень распространенная ошибка. Ее очень трудно обнаружить: вроде бы все работает, а потом вдруг раз — и непонятно каким образом данные исчезают из файла. По этой же причине, даже если каждый раз нужно стирать содержимое файла, ни в коем случае не используйте режим открытия w! Применяйте режим r+ и функцию ftruncate(). Например:

Не применяйте режимамы w и w+. Режимы w и w+ не совместимы с функцией fiock().

К сожалению, режим r+ требует обязательного существования файла. Если файла нет, произойдет ошибка. Важно ясно понимать, что использовать код наподобие идущего далее ни в коем случае нельзя. Никогда так не делайте:

В самом деле, между вызовом fiie_exists() и срабатыванием fopen() проходит какой-то промежуток времени — пусть и небольшой, в который может «вклиниться» другой процесс. Представьте, что произойдет, если он как раз в это время создаст файл, а его тут же очистите. То, что промежуток времени невелик, еще не означает, что вероятность «вклинивания» исчезающе мала, потому что современные операционные системы переключают процессы по весьма хитрым алгоритмам, существенно связанным с событиями ввода/вывода. Так как вызовы file_exists() и fopen() — по сути, две независимых операции ввода/вывода, после первой запросто может произойти переключение процесса. И получится, что файл буквально увели из под носа у скрипта.

Почему сразу не использовать режим а+? Ведь он, с одной стороны, открывает файл на чтение и запись, с другой — не уничтожает уже существующие файлы, а с третьей — создает пустой файл, если его не было на момент вызова. К сожалению, в некоторых версиях операционной системы FreeBSD с режимом а+ наблюдаются проблемы: при его использовании РНР позволяет писать данные только в конец файла, а любая попытка передвинуть указатель через fseek() оказывается неуспешной. Даже вызов ftruncate() возвращает ошибку. Так что не рекомендуется применять режим а+, если только не записываете данные исключительно в конец файла.

Функция fclose() перед закрытием файла всегда снимает с него блокировку, так что чаще всего не приходится делать это вручную. Тем не менее иногда бывает удобно долго держать файл открытым, блокируя его лишь изредка, во время выполнения операций записи. Чтобы не задерживать другие процессы, после окончания изменения файла в текущей итерации (и до начала нового сеанса изменений) файл можно разблокировать при вызове flock(Sf, LOCK UN). И вот тут поджидает другая западня. Все дело в буферизации файлового ввода/вывода. Разблокировав файл, должны быть уверены, что данные к этому моменту уже «сброшены» в файл. Иначе возможна ситуация записи в файл уже после снятия блокировки, что недопустимо. Всегда следите за тем, чтобы перед операцией разблокирования был вызов fflush().

— устанавливайте исключительную блокировку, когда хотите изменять файл;

— всегда используйте при этом режим открытия r, r+ или а+;

— никогда и ни при каких условиях не применяйте режимы w и w+, как бы этого ни хотелось.

— снимайте блокировку так рано, как только сможете, и не забывайте перед этим вызвать fflush().

Разделяемая блокировка. Теперь данные из нескольких процессов-писателей не будут перемешиваться, но как быть с процессорами-читателями? А вдруг процесс-читатель захочет прочитать как раз из того места, куда пишет процесс-писатель?

Существуют два метода обхода этой проблемы. Первый — это использовать все ту же исключительную блокировку. Действительно, кто сказал, что исключительную блокировку можно применять только в процессах, изменяющих файл? Ведь функция flock() не знает, что будет выполнено с файлом, для которого она вызвана. Однако этот метод неудачен. Представьте, что процессов-читателей много, а писателей — мало, и к тому же писатели еще и вызываются, скажем, раз в пару минут, а не постоянно, как читатели. В случае использования исключительной блокировки для процессов-читателей, довольно интенсивно обращающихся к файлу, очень скоро получим целый рой, пока очередному процессу разрешат читать. Но ведь никакой «аварии» не случится, если один и тот же файл будут читать и сразу все процессы этого роя? Ведь чтение из файла его не изменяет. Итак, предоставив исключительную блокировку для читателей, потенциально получаем проблемы с производительностью, перерастающие в катастрофу, когда процессов-читателей становится больше некоторого определенного порога.

Второй (и лучший) способ подразумевает использование разделяемой блокировки. Процесс, который устанавливает этот вид блокировки, будет приостановлен только в одном случае: когда активен другой процесс, установивший исключительную блокировку. То есть процессы-читатели будут «поставлены в очередь» только тогда, когда активизируется процесс-писатель. И это правильно. Посудите сами: зачем зажигать красный свет на перекрестке, если поперечного движения заведомо нет? Машинам ведь не обязательно проезжать перекресток в одном направлении по одной, можно и всем потоком.

Что должен делать процессор-писатель, если кто-то читает из файла, в который он как раз собирается записывать? Очевидно, должен дождаться, пока читатель не закончит работу. Иными словами, вызов flock($f, LOCK_EX) обязан подождать, пока активна хотя бы одна разделяемая блокировка. Это и происходит в действительности.

Дело в том, что, если почти всегда активна разделяемая блокировка, операционная система все равно так распределяет кванты времени, что в некоторые из них можно «включить» исключительную блокировку.

Модель процесса, использующего разделяемую блокировку:

Предыдущий код программи блокировки отличается лишь комментариями да константой LOCK_SH вместо LOCK_EX.

— устанавливайте разделяемую блокировку, когда собираетесь только читать из файла, не изменяя его;

— всегда используйте при этом режим открытия r или r+, и никакой другой;

— снимайте блокировку так рано, как только сможете.

Блокировки с запретом «подвисания». Как следует из описания функции fiock(), к ее второму параметру можно прибавить константу LOCK_NB для того, чтобы функция не ожидала, когда программа может «двинуться в путь», а сразу же возвращала управление в основную программу. Это может пригодиться, если не хотите, чтобы сценарий бесполезно простаивал, ожидая, пока ему разрешат обратиться к файлу. В эти моменты, возможно, лучше будет заняться какой-нибудь полезной работой — например, почистить временные файлы, память, или же просто сообщить пользователю, что файл заблокирован, чтобы он подождал и не думал, что программа зависла.

Пример использования исключительной блокировки в совокупности с LOCK_NB:

Эта программа основывается на том факте, что выход из flock() может произойти либо в результате отказа блокировки, либо после того, как блокировка будет установлена — но не до того. Когда наконец-то дождемся разрешения доступа к файлу, и произойдет выход из цикла while, будем иметь исключительную блокировку, закрепленную за нашим файлом.

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

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

Как правильно читать файлы с помощью PHP

Об использовании функций fopen, fclose, feof, fgets, fgetss, и fscanf

Давайте перечислим все возможности

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

Традиционные методы fopen

Методы fopen , возможно, лучше других знакомы программистам C и C++ былых времен, поскольку в большей или меньшей степени являются именно теми инструментами, которые на протяжении долгих лет были всегда у вас под рукой, если вы работали с этими языками программирования. Для любого из этих методов вы выполняете стандартную процедуру, используя fopen для открытия файла, функцию для чтения данных, а затем fclose для закрытия файла, как показано в Листинге 1.

Листинг 1. Открытие и чтение файла с помощью fgets

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

  1. Открываете файл. $file_handle хранит ссылку на сам файл.
  2. Проверяете, не достигли ли вы конца файла.
  3. Продолжаете считывание файла, пока не достигнете конца, печатая каждую строку, которую читаете.
  4. Закрываете файл.

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

Функция fopen

Функция fopen устанавливает связь с файлом. Я говорю «устанавливает связь, » поскольку, кроме открытия файла, fopen может открыть и URL:

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

Примечание: Параметр «r» , использованный в fopen , указывает на то, что файл открыт только для чтения. Поскольку запись в файл не входит в круг вопросов, рассматриваемых в данной статье, я не стану перечислять все возможные значения параметра. Тем не менее, вам необходимо изменить «r» на «rb» если вы производите чтение из двоичных файлов для межплатформенной совместимости. Ниже будет приведен пример данного типа.

Функция feof

Команда feof определяет, произведено ли чтение до конца файла, и возвращает значение True (Истина) или False (Ложь). Цикл, приведенный в Листинге 1 продолжается, пока не будет достигнут конец файла «myfile.» Обратите внимание, что feof также возвращает False, если вы читаете URL и произошло превышение времени ожидания подключения, поскольку не имеется более данных для считывания.

Функция fclose

Пропустим середину Листинга 1 и перейдем в конец; fclose выполняет задачу, противоположную fopen : она закрывает подключение к файлу или URL. После выполнения данной функции вы больше не сможете выполнять чтение из файла или сокета.

Функция fgets

Возвращаясь на несколько строк назад в Листинге 1, вы попадаете в самый центр процесса обработки файлов: непосредственно чтение файла. Функция fgets — это выбранное вами «оружие» для первого примера. Она захватывает строчку данных из файла и возвращает ее как строку. Оттуда вы можете выводить данные или обрабатывать их иным образом. В примере, приведенном в Листинге 1, распечатывается весь файл целиком.

Если вы решите ограничить размер порции данных, с которой работаете, можно добавить fgets аргумент для ограничения максимальной длины строки захватываемых данных. Например, используйте следующий программный код для ограничения длины строки в 80 символов:

Вспомните «\0», указатель конца строки в C и установите длину на один символ больше, чем вам в действительности необходимо. Как видите, в приведенном выше примере используется 81, тогда как вам нужно 80 символов. Сделайте вашей привычкой добавление дополнительного символа всегда, когда вам понадобится задать ограничение длины строки для данной функции.

Функция fread

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

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

В приведенном выше примере считывается 4096 байтов (4 KB) данных. Обратите внимание, что, независимо от указанного вами значения, fread будет считывать не более 8192 байтов (8 KB).

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

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

Функция fscanf

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

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

Функция fgetss

Функция fgetss отличается от традиционных функций для работы с файлами и дает вам лучшее представление о возможностях PHP. Она работает наподобие fgets , но отбрасывает любые обнаруженные ею теги HTML или PHP, оставляя только «голый» текст. Возьмем приведенный ниже HTML-файл.

Листинг 2. Пример файла HTML

Пропустим его через функцию fgetss .

Листинг 3. Использование fgetss

Вот что вы получите в качестве выходных данных:

Функция fpassthru

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

Эта функция выводит данные на печать, поэтому вам не нужно помещать их в переменную.

Нелинейная обработка файла: перемещение по файлу

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

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

Начиная с PHP V4.0, доступны также несколько других опций. Например, если нужно перейти вперед на 100 байт от вашей текущей позиции, вы можете использовать следующий код:

Аналогично, переход назад на 100 байт осуществляется посредством:

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

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

Примечание: вы не можете использовать fseek в дескрипторах файла, ссылающихся на URL.

Захват целого файла

Теперь мы переходим к рассмотрению некоторых уникальных возможностей PHP для обработки файлов: обработка больших блоков данных в одной или двух строках. Например, как можно захватить файл и вывести все его содержимое на вашу Web-страницу? Что же, вы видели пример использования цикла с fgets . Но как сделать это проще? Процесс почти смехотворно прост при использовании fgetcontents , которая помещает весь файл в строку.

Хотя это и не лучший вариант, вы можете записать эту команду еще короче:

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

Это команда фактически та же, что и:

Должно быть, вы смотрите на эти примеры и думаете, «Это все-таки слишком трудоемкий способ». PHP-разработчики согласны с вами. Поэтому вы можете сократить приведенную выше команду до:

Функция readfile передает на вывод все содержимое файла или Web-страницы в выходной буфер по умолчанию. По умолчанию эта команда выводит сообщение об ошибке при сбое. Во избежание такого поведения (если вы этого хотите), попробуйте команду:

Конечно, если вам необходимо обрабатывать содержимое файлов, то одна строка, возвращаемая file_get_contents — это, пожалуй, слишком. Вы, возможно, захотите сначала разбить ее на части с помощью функции split() .

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

Следует заметить, что между двумя приведенными выше примерами есть небольшое отличие. Команда split удаляет знаки перехода на новую строку, тогда как при использовании команды file строки массива оканчиваются знаками перехода на новую строку (также, как и при использовании fgets ).

Возможности PHP, тем не менее, далеко превосходят описанные выше. Вы можете разбить целые .ini-файлы в стиле PHP всего одной командой parse_ini_file . Команда parse_ini_file применима к файлам, сходным с приведенным в Листинге 4.

Листинг 4. Пример файла .ini

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

В результате будут получены следующие выходные данные:

Листинг 5. Выходные данные

Конечно, вы можете заметить, что данная команда объединила разделы. Это действие по умолчанию, но вы легко можете произвести необходимую настройку, воспользовавшись вторым аргументом parse_ini_file : process_sections , который является переменной логического типа (Boolean). Установите значение process_sections как True (истина).

И ваши выходные данные будут иметь вид:

Листинг 6. Выходные данные

PHP помещает данные в легко разбиваемый для анализа многомерный массив.

Но это лишь верхушка айсберга, если говорить об обработке файлов в PHP. Более сложные функции, например tidy_parse_file и xml_parse могут помочь вам с обработкой соответственно HTML- и XML-документов. Обратитесь к разделу Ресурсы, чтобы получить более подробную информацию о работе этих функций. Обе они стоят внимания, если вы будете работать с файлами указанных типов, но вместо рассмотрения всех возможных типов файлов, вы можете внимательно ознакомиться с содержанием данной статьи, где есть несколько неплохих общих правил по работе с функциями, описанными мной к настоящему моменту.

Хороший стиль программирования

Никогда не считайте, что все в вашей программе будет работать так, как было задумано. Например: что, если файл, который вы ищете, был перемещен? Что, если в результате изменения прав доступа вы не можете прочитать содержимое файла? Можно заранее проверить наличие файла и права на его чтение, воспользовавшись методами file_exists и is_readable .

Листинг 7. Использование file_exists и is_readable

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

Поскольку fopen возвращает значение False в случае неудачного выполнения, это послужит гарантией того, что обработка файла будет производиться только в том случае, если файл удалось открыть. Конечно, если файл не существует или нечитаем, вы ожидаете, что возвращаемое значение будет отрицательным. Следовательно такая проверка представляет собой ловушку, в которую попадают все потенциально возможные неполадки. В качестве альтернативы можно использовать завершение работы программы или вывод сообщения об ошибке, если не удается открыть файл.

Как и fopen , функции file_get_contents , file и readfile возвращают значение False, если не удается открыть или обработать файл. Функции fgets , fgetss , fread , fscanf и fclose также возвращают значение False при возникновении ошибки. Конечно, за исключением fclose , вы, вероятно уже обработали возвращенные ими результаты. Что касается fclose , мало что можно сделать, если дескриптор файла не закрывается должным образом, поэтому проверка возвращенного значения функции fclose , как правило, является излишней.

Выбор за вами

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

Если вы обрабатываете большие объемы данных, вероятно, fscanf окажется более полезной и эффективной, чем, скажем, использование file в сочетании с последующими командами split и sprintf . Если же вы просто отображаете текст большого объема с незначительными изменениями, напротив, использование функций file , file_get_contents , или readfile , возможно, будет более целесообразным. Это решение, вероятно, будет верным при использовании PHP для кэширования или даже создания временного прокси сервера.

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

Ресурсы для скачивания

Похожие темы

  • Оригинал статьи: The right way to read files with PHP.
  • PHP.net — полный справочник по PHP на все случаи жизни.
  • Прочитайте «PHP через примеры, Часть 1» и откройте для себя упрощенный метод PHP для построения сложных и мощных программ для Web.
  • Узнайте о функции xml_parse , которая не рассматривается в данной статье.
  • Узнайте о функции tidy_parse_file , которая не рассматривается в данной статье.
  • PHP.net — отличный ресурс для PHP-разработчиков.
  • Ознакомьтесь с «Рекомендуемым списком книг по PHP.»
  • Просмотрите все связанные с PHP материалы на developerWorks.
  • Усовершенствуйте ваши навыки программирования на PHP, ознакомившись с ресурсами проекта PHP на сайте IBM developerWorks.
  • Посетите Раздел Open Source на developerWorks для получения разнообразной информации о средствах и методах разработки ПО, инструментальных средств и обновлений проектов, что поможет вам в разработке технологий с открытым исходным кодом и использовании их с программными продуктами IBM.
  • Рационализируйте свой следующий проект по разработке ПО с открытым исходным кодом с помощью пробного ПО IBM, доступного на DVD или для загрузки.
  • Посетите Safari Books Online, где представлено множество ресурсов по технологиям с открытым исходным кодом.

Комментарии

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

php создание файла, чтение и запись

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

Чтобы создать файл на php в исполняемом скрипте надо всего лишь указать несколько функций:

Рассмотрим сразу пример:

Тут вы должны знать :

fopen() — функция открывает файл чтения или для записи и уточнениями;

Это уточнения (параметр mode функции fopen) очень важно:

  • «r» — открыть файл в php ТОЛЬКО для чтения . Курсор помещается в начало.
  • «r+» — открыть файл в php для чтения и для записи . Курсор помещается в начало. . — при этих двух режимах r и r+ файлы уже должны быть созданы(иначе вылезет ошибка Warning: fopen(file.txt) [function.fopen]: failed to open stream: No such file or directory in . ), а мы лишь читаем или у нас есть возможность дописывать.
  • «w» — открывается файл ТОЛЬКО для записи. Файл урезается до нулевой длины — то есть затирается. Записывается, что нужно и Курсор ставится в начало.
  • «w+» — открывается файл для записи И ЧТЕНИЯ! Остальное то же самое что и в режиме «w». . — при этих двух режимах — если файл не был создан — ПРЕДПРИМЕТСЯ ПОПЫТКА ЕГО СОЗДАТЬ!
  • «a» — открыть файл ТОЛЬКО для записи. В отличие от «w» этот параметр не затирает содержимое файла, а ставит курсор в конец строки и добавляет в конец содержимое, которое мы хотели добавить.
  • «a+» — открыть файл для записи и чтения.

fwrite($fp, $text) — функция записи в файл на php — то есть то что находится в переменной $text записывается в файл, который находится в переменной $fp;

fclose($fp) — функция закрытия файла, который мы записали в переменную $fp;

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

Полезные дополнения и функции PHP для работы с открытым файлом:

while(!feof($fp)) <
$mytext = fgets($fp, 99);
echo $mytext.»
«;
>

здесь выполняется условие — «пока не достигнут конец файла то делай то то» while(!feof($fp))

1. Функция fgets ($fp, 99) — позволяет разделить все содержимое на участки в 99 байт и далее, чтобы это отчетливее увидеть мы помещаем тег

Эта функция string fgets ( resource handle [, int length] ) по умолчанию принимает в параметр length 1024 байта(1 килобайт), если не указать так и будет. Этот параметр необязателен с PHP 4.2.0 (В случае ошибки возвращает FALSE)

Доп функции для открытия, записи и создания файла

Функция — int readfile ( string filename [, bool use_include_path [, resource context]] ) — считываем файл как единое целое.

Читает файл и записывает содержимое в буфер вывода. И возвращает количество выведенных байт. В случае ошибки вернет, если не использована собачка — @readfile.

Что-то подобное получится:

В конце слова тег стоят
.

б. Функция — array file ( string filename [, int use_include_path [, resource context]] ), делает то же самое, что и функция readfile, за одним исключением она добавляет содержимое файла в массив:

Таким образом можно считывать любые странички в интернете: $lines = file(‘http://saitsozdanie.ru/’); и перебрать массив через функцию foreach;

3а. Функция string file_get_contents ( string filename [, bool use_include_path [, resource context [, int offset [, int maxlen]]]] ) — позволяет получить содержимое в виде одной строки.

Это более универсальная функция PHP для считывания файла, похожа на функцию file, только содержимое возвращается в строку, а не в массив и можно задавать условия — с какого байта начинать — offset и с какого заканчивать — maxlen. При неудаче вернет FALSE.

Важно. — в этом случае функция заменяет сразу 3: fopen(), fread() и fclose() и таким образом избавляет от мароки.

3б. Функция int file_put_contents ( string filename, mixed data [, int flags [, resource context]] ) — идентична последовательному вызову функций fopen(), fwrite() и fclose() — возвращает количество записанных байт.

Более новые статьи:

  • Для тех, кто только начинает изучать PHP — заголовки HTTP является каким-то туманом, который почему-то не особо приятный. давайте его рассеивать. Люб …

«>Заголовки HTTP через PHP — 04/03/2020 18:55
Часто в PHP нужно вывести все файлы и каталоги в виде списка. это нужно, чтобы нам сразу узнать где у нас, чего и сколько. давайте приступать. …

«>PHP вывод файлов и каталогов директории — 24/02/2020 20:59
На PHP часто нужна загрузка файлов на сервер. приятно же, если у вашего сайта есть возможность загружать файлы на сайт: картинки или другие текстовые …

Более старые статьи:

  • Конструкция switch — переключатель на php бывает в некоторых случаях незаменима, и увеличивает быстродействие. …

«>switch тонкости
На сайте часто могут возникать ошибки PHP, в этой статье будим их разбирать.

«>Ошибки PHP
Суперглобальный массив $_SERVER — это то на чем стоит остановится и изучить, если вы встали на путь программирования. Он вам может показать самую важн …

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

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

Функции чтения и записи файлов

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

Любой сеанс манипулирования файлом может состоять из описанных ниже шагов:

Открыть файл для чтения-записи.

Выполнить операцию чтения в файле.

Провести необходимые операции с содержимым файла.

Записать результаты в файл (если нужно).

Для выполнения каждого из этих шагов предусмотрена соответствующая функция работы с файловой системой языка PHP.

Операция открытия файла

Для открытия файлов используется функция fopen(). Результат выполнения функции fopen() необходимо присваивать переменной. Следует учитывать, что функция fopen() в результате успешного выполнения возвращает не целое число, а строку, в которой приведены данные «Resource id #n», где n — номер открытого в настоящее время потока. Не следует пытаться проконтролировать успешное выполнение операции открытия файла с помощью вызовов функции is_int() или is_numeric(). Вместо этого следует использовать функцию die().

Если операция открытия файла прошла успешно, интерпретатор PHP возвращает идентификатор ресурса, который требуется для осуществления дальнейших операций, таких как fread или fwrite. В противном случае будет получено значение false.

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

Режим только чтения («r»).

Режим чтения и записи, применяемый, если файл уже существует («r+»). Запись осуществляется в начало файла; а если файл считывается как строка, после чего эта строка редактируется и снова выводится в файл, то фактически происходит запись обновленного файла с сохранением его первоначального содержимого.

Режим только записи («w»), в котором перед выполнением каких-либо операций записи создается файл с указанным именем, если этот файл еще не существует, и стирается содержимое указанного файла, если он существует! Данный режим не может использоваться для чтения файла; он предназначен только для записи.

Режим записи и чтения, применяемый, даже если файл еще не существует («w+»), предусматривает создание файла с указанным именем (при условии, что он не существует) и удаление до начала выполнения операций записи содержимого указанного файла!

Режим только записи, применяемый для дополнения файла, независимо от того, существует ли файл или нет («a»).

Режим записи и чтения, применяемый для дополнения файла, независимо от того, существует ли файл или нет («а+»). Если файл считывается как строка, после чего эта строка редактируется и снова выводится в файл, то фактически происходит запись обновленного файла с сохранением первоначального содержимого файла.

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

Для работы с файлами предусмотрена возможность открывать несколько типов соединений и использовать средства доступа, включая HTTP, HTTPS, FTP, FTPS, стандартный ввод-вывод, и др.

При использовании функции fopen() для работы по протоколу HTTP предпринимается попытка открыть соединение по протоколу HTTP 1.0 для обработки файла такого типа, который обычно обрабатывается веб-сервером (таким как файл HTML, PHP, ASP и т.д.). По существу, интерпретатор PHP вынуждает веб-сервер действовать так, как будто переданный ему запрос поступил из обычного веб-браузера, применяемого для просмотра Интернета, а не был получен с помощью операции открытия файла:

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

При использовании функции fopen() для работы по протоколу FTP предпринимается попытка установить соединение FTP с удаленным сервером от имени FTP-клиента. Этот вариант применения функции fopen() является более сложным, поскольку в данном случае, кроме имени хоста и пути к файлу, приходится также указывать имя пользователя и пароль FTP, как показано ниже:

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

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

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

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

Операции чтения файла

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

При использовании указанной конструкции часто возникает ошибка, состоящая в том, что применяется вызов filesize($fd), а не filesize($filename).

Функция fread() исключительно полезна, поскольку позволяет преобразовать любой файл в строку, с которой в дальнейшем могут осуществляться манипуляции с помощью широкого перечня полезных строковых функций PHP. К тому же любую строку можно преобразовать в массив с использованием таких функций, как file() или explode(), что позволяет получить доступ к большому арсеналу функций манипулирования массивами языка PHP.

Начиная с версии PHP 4.3.0 пользователям предоставлен доступ к новой функции — file_get_contents(). Эта функция возвращает все содержимое файла в виде строки и обладает возможностями функции fopen(). Применение функции file_get_contents() равносильно применению функций fopen() и fread().

Если требуется и выполнять чтение, и применять к файлу операции построчной обработки, то вместо функции fread() можно использовать функцию fgets(). Начиная с версии PHP 4.2.0 по умолчанию предусмотрено, что функция возвращает по 1024 байта в расчете на каждую строку, если в качестве второго параметра функции fgets() не задана длина строки.

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

Операции записи файла

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

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

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

Операции закрытия файла

Операция закрытия файла является несложной:

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

Ниже показан полный пример чтения и записи файла из текущей файловой системы:

Код PHP ‘; fclose($fd); echo ‘Запись в файл

‘; $fd = fopen($filename, «w+») or die(«Файл нельзя открыть»); fwrite ($fd, ‘Hello, world!’); fclose($fd);

Чтение из файла

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

Функция feof

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

Функция file_exists

функция file_exists — это простая функция, к использованию которой приходится прибегать очень часто, если для доступа к данным применяются функции файловой системы. Эта функция просто проверяет наличие в локальной файловой системе файла с указанным именем, как показано ниже:

Функция возвращает значение true, если файл существует, а если файл не найден, возвращает значение false. Результаты проверки сохраняются в кэше, который может быть очищен с помощью функции clearstatcache().

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

Работа с файлами разделяется на 3 этапа:

  1. Открытие файла.
  2. Манипуляции с данными.
  3. Закрытие файла.

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

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

$fp = fopen(‘counter.txt’, ‘r’);

Согласно документации PHP выделяют следующие виды режимов файлов:

  1. r – открытие файла только для чтения.
  2. r+ — открытие файла одновременно на чтение и запись.
  3. w – создание нового пустого файла. Если на момент вызова уже существует такой файл, то он уничтожается.
  4. w+ — аналогичен r+, только если на момент вызова фай такой существует, его содержимое удаляется.
  5. a – открывает существующий файл в режиме записи, при этом указатель сдвигается на последний байт файла (на конец файла).
  6. a+ — открывает файл в режиме чтения и записи при этом указатель сдвигается на последний байт файла (на конец файла). Содержимое файла не удаляется.

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

Для демонстрации рассмотрим следующий сценарий:

II. Манипуляции с данными файла

Записывать данные в файл при помощи PHP можно при помощи функции fwrite(). Это функция принимает 2 обязательных параметра и 1 необязательный. В качестве обязательных параметров выступает дескриптор файла и режим файла:

Для построчного считывания файла используют функцию fgets(). Функция принимает 2 обязательных параметра:

Примечание: В данном примере значение 999 определяет количество символов, которые будут считываться до тех пор, пока указатель не достигнет конца файла (EOF).

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

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

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

Примечание: Не следует применять функцию file() к двоичным файлам (binary-safe), т.к. она не является безопасной в плане считывания двоичных файлов, если при этом, где-то встретиться символ конца файла (EOF), то она не гарантирует вам чтение всего двоичного файла.

В конце статьи, вы найдете хороший «сборник рецептов» по массивам, который дает решение многих проблем, с которыми ежедневно встречается веб-программист.

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

III. Закрытие файла

Закрытие файла происходить с помощью функции fclose(), которая принимает 1 обязательный параметр.

Сборник рецептов

1) Нам необходимо проверить существует ли тот или иной файл. Для этого мы воспользуемся функцией file_exists().

Примечание: Функция file_exists не производит проверку файлов на удаленном веб-сервере. Для правильной работы функции, файл со скриптом должен находиться на том сервере, где и проверяемый файл.

2) Определяем размер файла с помощью функции filesize()

3) Создание временного файла с помощью функции tmpfile()

4) Вам необходимо определить количество строк в файле. Для этого используем функцию count()

5) Нам необходимо использовать механизм блокировки файла

6) Нам необходимо удалить определенную строку из файла

7) Определение типа файла. Используем функцию filetype(), которая принимает единственный параметр

После вызова строка может содержат одно из следующих значений:

  1. file – обычный файл
  2. dir – каталог
  3. ink – символическая ссылка
  4. fifo – fifo-канал
  5. block – блочно — ориентированное устройство
  6. char – символьно — ориентированное устройство
  7. unknown – неизвестный тип файла

8) Если вы хотите просмотреть все параметры файла, то следует воспользоваться функцией stat()

9) Нам необходимо очистить файл, используем функцию ftruncate()

10) Нам необходимо узнать дату последнего изменения файла, используем функцию filectime(). Функция возвращает значение времени в форме Unix timestamp.

Безопасная работа с файлами в PHP

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

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

Для этого в PHP используются функции блокировки файла. Принцип заключается в следующем:

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

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

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

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

Все это конечно хорошо, но я бы сравнил это с маршрутом Киев — Москва через Минск. Во-первых, это и намного дольше времени займет, во-вторых, гораздо больше использованных ресурсов и средств.

Видел случаи, когда используют Функцию Sleep, которая задерживает выполнение программы на данное количество секунд. Скажу прямо, все эти выдумки только замедляют работу скрипта, а затем все обсуждают, что работа с файлами медленная, и не эффективна! А все из за того, что скрипты вовсе не оптимизированы.

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

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

Нужно помнить, что функция ничего не блокируют. Это только флажки, проверка которых лежит на плечах программистов. То есть, во всех скриптах, которые работают с определенным файлом, нужно так же обязательно использовать Flock!

И так, давайте разберем все на примере.

Запись данных в файл осуществляется так:
А так нужно считывать данные:
Вот и вся техника безопасности при работе с файлами.

Илон Маск рекомендует:  margin-bottom в CSS
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL