Файл PHP существует

Обновлено: 21.11.2024

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

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

Важность проверки существования файла

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

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

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

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

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

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

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

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

Важно помнить, что и is_file(), и is_dir() возвращают false даже для путей, которые действительно существуют, если у родительского каталога нет правильных разрешений.

Проверить, существует ли файл и доступен ли он для чтения или записи

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

Как следует из названия, функция is_readable() проверяет две вещи: во-первых, факт существования файла или каталога и, во-вторых, возможность чтения файла. Точно так же функция is_writable() также проверяет две вещи: файл или каталог существует и доступен для записи.

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

Остерегайтесь кешированных результатов

Значение, возвращаемое вызовом всех этих пяти функций, а именно, file_exists(), is_file(), is_dir(), is_readable() и is_writeable(), кэшируется. Это означает, что повторные вызовы функции, скажем, is_file() , могут привести к устаревшим результатам.

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

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

Если вы запустите приведенный выше фрагмент кода для реально существующего файла, а затем удалите его вручную, пока скрипт ждет, вызов is_file() все равно вернет значение true . Однако вы можете получить правильные результаты, просто вызвав clearstatcache() перед повторным запросом существования файла.

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

Заключительные мысли

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

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

Вывод: в этом руководстве вы узнаете, как проверить, существует ли файл в PHP, используя функции file_exists() , is_file() , is_readable() и is_writable().

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

Проверка существования файла с помощью функции file_exists()

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

Функция file_exists() принимает имя файла и возвращает значение true, если файл существует; в противном случае возвращается false .

В следующем примере функция file_exists() используется для проверки существования файла readme.txt в текущем каталоге:

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

…иначе вы увидите другое сообщение:

Обратите внимание, что $filename также может быть путем к каталогу. В этом случае функция file_exists() возвращает значение true, если каталог существует.

Проверка существования файла с помощью функции is_file()

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

Функция is_file() принимает $filename и возвращает true, если $filename является файлом и существует:

В следующем примере функция is_file() используется для проверки существования файла readme.txt:

Проверить, существует ли файл и доступен ли он для чтения

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

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

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

Проверить, существует ли файл и доступен ли он для записи

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

Функция is_writable() возвращает true, если $filename существует и доступен для записи, или false в противном случае.

В Windows используйте //имя_компьютера/общий_ресурс/имя_файла или \\имя_компьютера\общий_ресурс\имя_файла, чтобы проверить файлы в общих сетевых ресурсах.

Возвращаемые значения

Возвращает значение true, если файл или каталог, указанный в имени файла, существует; false в противном случае.

Примечание.

Эта функция возвращает значение false для символических ссылок, указывающих на несуществующие файлы.

Примечание:

Проверка выполняется с использованием реального UID/GID вместо действующего.

Примечание. Поскольку целочисленный тип PHP является знаковым, а многие платформы используют 32-битные целые числа, некоторые функции файловой системы могут возвращать неожиданные результаты для файлов размером более 2 ГБ.

Ошибки/Исключения

В случае сбоя выдается E_WARNING.

Примеры

if ( file_exists ( $filename )) echo "Файл $filename существует" ;
> else echo "Файл $filename не существует" ;
>
?>

Примечания

Примечание. Результаты этой функции кэшируются. Подробнее см. в разделе clearstatcache().

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

См. также

  • is_readable() — сообщает, существует ли файл и доступен ли он для чтения
  • is_writable() — сообщает, доступно ли имя файла для записи
  • is_file() — сообщает, является ли имя файла обычным файлом
  • file() — считывает весь файл в массив
  • Информация о SplFileInfo

Пользовательские заметки 30 заметок

Примечание. Результаты этой функции кэшируются. Подробнее см. в разделе clearstatcache().

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

Мне нужно было измерить производительность проекта, поэтому я провел простой тест с миллионом проверок file_exists() и is_file(). В одном сценарии существовало только семь файлов. Во втором все файлы существовали. is_file() требуется 3.0 для сценария 1 и 3.3 секунды для второго сценария. file_exists() потребовалось 2,8 и 2,9 секунды соответственно. Абсолютные числа, конечно, не зависят от системы, но они ясно указывают на то, что file_exists() работает быстрее.

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

В ответ на предложение seejohnrun проверить, существует ли URL. Даже если файл не существует, вы все равно получите заголовки 404. Вы по-прежнему можете использовать get_headers, если у вас нет возможности использовать CURL..

Если вы пытаетесь получить доступ к общему сетевому ресурсу Windows, вам необходимо настроить веб-сервер с достаточными разрешениями, например:

Вы получите сообщение об ошибке, говорящее о том, что имя пути не существует, это будет связано с тем, что Apache или IIS работают как LocalSystem, поэтому вам придется войти в Службы и настроить Apache на «Открыть сеанс как». Создайте нового пользователя, у которого достаточно разрешения, а также убедитесь, что у целевого общего ресурса есть соответствующие разрешения.

Надеюсь, это сэкономит кому-нибудь несколько часов исследований.

file_exists() НЕ ищет ваш файл в php include_path, поэтому не используйте его перед попыткой включить или потребовать.

@$result = включить $filename;

Да, include возвращает false, если файл не найден, но также генерирует предупреждение. Вот почему вам нужен @. Не пытайтесь обойти проблему с предупреждением, используя file_exists(). Это заставит вас чесать голову, пока вы не поймете или не наткнетесь на тот факт, что file_exists() НЕ ИЩЕТ PHP INCLUDE_PATH.

всегда возвращает "отсутствует", даже для существующего URL.

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

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

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

функция url_exists ($url) $url = str_replace("http://", "", $url);
if (strstr ($url, "/")) $url = взорвать ("/", $url, 2);
$url [ 1 ] = "/" . $ URL [ 1 ];
> else $url = array( $url , "/" );
>

$fh = fsockopen ( $url [ 0 ], 80 );
if ( $fh ) fputs ( $fh , "GET" . $url [ 1 ]. " HTTP/1.1\nHost:" . $url [ 0 ]. "\n\n" );
if ( fread ( $fh , 22 ) == "HTTP/1.1 404 не найдено" ) < return FALSE ; >
еще

Вот более простая версия url_exists:

Если файл, проверяемый функцией file_exists(), является файлом в символически связанной структуре каталогов, результаты зависят от разрешений узла дерева каталогов под связанным деревом. PHP на веб-сервере (т. е. apache) будет учитывать разрешения файловой системы под символической ссылкой, в отличие от PHP в качестве сценария оболочки, который учитывает разрешения связанных каталогов (т. е. сверху и видим).

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

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

функция fileExists ( $path ) возвращает (@ fopen ( $path , "r" )== true );
>
?>

к сожалению, file_exists не может' не достигают удаленных серверов, поэтому я использовал функцию fopen.

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

foreach ( $possibles as $poss )
<
if ( file_exists (SITE_RANGE_IMAGE_PATH . $this -> range_id . '/ ' . $poss . '.jpg' ))
<
// существует
>
еще
<
// не найдено
>
>
?>

поэтому вы должны сделать:

foreach ( $possibles as $poss )
<
$img = SITE_RANGE_IMAGE_PATH . $это -> диапазон_идентификатор. '/' . $ возможно . '.jpg'
if ( file_exists ( $img ))
<
// существует
>
else
<
// нет нашел
>
>
?>

Тогда все будет работать нормально.

По крайней мере, так обстоит дело в этой системе Windows с php 5.2.5 и apache 2.2.3

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

Я написал эту маленькую удобную функцию, чтобы проверить, существует ли изображение в каталоге, и если да, то вернуть несуществующее имя файла, например. если вы попробуете 'flower.jpg' и он существует, то он попробует 'flower[1].jpg', а если он существует, он попробует 'flower[2].jpg' и так далее. У меня работает нормально. Конечно, вы можете использовать его и для других типов файлов, кроме изображений.

функция imageExists ( $image , $dir )

$i = 1 ; $probeer = $изображение ;

У меня были проблемы с file_exists при использовании URL-адресов, поэтому я сделал эту функцию:

функция file_exists_2 ( $filePath )
return ( $ch = curl_init ( $filePath )) ?@ curl_close ($ch) || true : false ;
>
?>

Ура!

Примечание к записи openspecies (отлично, кстати, спасибо!).

Если ваш сервер не может разрешить собственный DNS, используйте следующее:
$f = preg_replace('/www\.yourserver\.(net|com)/', getenv('SERVER_ADDR'), $f );

Непосредственно перед $h = @get_headers($f); линия.

Замените расширения (net|com|. ) в выражении регулярного выражения соответствующим образом.

Я сделал немного кода, который видит, есть ли файл, отправляемый через RTSP, или нет:

функция rtsp_exists ( $url )

$server = parse_url ($url, PHP_URL_HOST);
$port = "554" ;
$hdrs = "ОПИСАТЬ" . $ URL . «РТСП/1.0». "\r\n\r\n" ;

//Открыть соединение (время ожидания 15 с)
$sh = fsockopen ($server, $port, $err, $err_otp, 15);
//Проверка соединений
if(! $sh ) return false ;
//Отправить заголовки
fputs ( $sh , $hdrs );
//Получить данные (1 КБ)
$rtds = fgets ( $sh , 1024 );
//Закрываем сокет
fclose ( $sh );

return strpos ( $rtds , "200 OK" ) > 0 ;
>
?>

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

Например, если вы запускаете подпрограмму PHP, например, из корневой папки вашего веб-сайта и спрашиваете:

Вы получите FALSE, даже если этот файл существует не в корне.

Вам нужно добавить

Старые версии php (v4.x) не работают с функцией get_headers(). Так что я сделал это и работает.

function url_exists ( $url ) // Поддерживается версия 4.x
$handle = curl_init ( $url );
if (false === $handle)
return false;
>
curl_setopt ($handle, CURLOPT_HEADER, false);
curl_setopt ($handle, CURLOPT_FAILONERROR, true); // это работает
curl_setopt ($handle, CURLOPT_NOBODY, true);
curl_setopt ($handle, CURLOPT_RETURNTRANSFER, false);
$connectable = curl_exec ($handle);
curl_close ($handle);
return $connectable ;
>
?>

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

if( file_exists ( $_SERVER < 'DOCUMENT_ROOT' >. "/my_images/abc.jpg" )) <
.
>
?>

Не забудьте поставить косую черту '/', например мой корень документа в Ubuntu — это /var/www без косой черты.

file_exists не сможет найти ваш файл, если права доступа к файлу не включены для «другого», когда он не принадлежит вашему пользователю php. Я думал, что у меня возникли проблемы с именем каталога, в котором есть пробел (/users/andrew/Pictures/iPhoto Library/AlbumData.xml), но на самом деле не было разрешений на чтение для изображений, iPhoto Library или AlbumData.xml. . Как только я это исправил, file_exists заработал.

file_exists() вернет FALSE для неработающих ссылок

$ ln -s do_not_exist my_link
$ ls -l
lrwxr-xr-x 1 группа пользователей 14 May 13 17:28 my_link -> is_not_exist
$ php -r "var_dump( file_exists('my_link'));"
bool(false)

Я провел последние два часа, пытаясь понять, что не так с моим оператором if: file_exists($file) возвращал false, однако я без проблем мог вызвать include($file).

Оказывается, я не понимал, что значение php include_path, которое я установил в файле .htaccess, не переносилось в file_exists, is_file и т. д.

// .htaccess php_value include_path '/home/user/public_html/';

// включает ложь в /home/user/public_html/includes/

//не работает, file_exists возвращает false
if ( file_exists ( 'includes/config.php' ) )
include( 'includes/config.php' );
>

//работает, file_exists возвращает true
if ( file_exists ( '/home/user/public_html/includes/config.php' ) )
include( 'includes/config.php' );
>
?>

Просто показывает, что «ярлыки для простоты», такие как установка include_path в .htaccess, в конечном итоге могут вызвать еще больше проблем.

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

функция generateRandomString ( $length = 8 )
<
$string = "" ;

//символ, который можно использовать
$possible = "0123456789bcdfghjkmnpqrstvwxyz" ;

for($i = 0; $i $length; $i++)
<
$char = substr($possible, rand(0, strlen($possible)-1), 1);

if (! strstr ( $string , $char ))
<
$string .= $char ;
>
>

функция randomFile ($folder = '', $extension = '')
<
$folder = trim ($folder);
$folder = ( $folder == '' ) ? './' : $папка ;

//проверяем, существует ли каталог
if (! is_dir ( $folder ))

//генерируем путь к файлу
$filepath = $folder . "/" . генерировать случайную строку ( 128 ) . $расширение ;

//проверить, существует ли этот путь к файлу, если он существует, если генерируется снова
//до тех пор, пока не будет найден несуществующий
while( file_exists ( $filepath ))
<
$filepath = $папка . "/" . генерировать случайную строку ( 128 ) . $расширение;
>

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

функция __autoload ( $name )
<
$path = взорвать ( ":" , ini_get ( 'include_path' )); //получаем все возможные пути к файлу (предварительно загруженному с файловой структурой проекта)
foreach( $path as $tryThis )
<
//пробуем каждую возможную итерацию файла имя и использовать первое попавшееся имя
// name.class.php first
$exists = file_exists ( $tryThis . '/' . $name . '.class.php' );
if ( $exists )
<
include_once( $name . '.class.php' );
возврат;
>

//хорошо, это не сработало, попробуйте наоборот
$exists = file_exists ( $tryThis . '/' . 'class.' . $name . '.php' );
if ( $exists )
<
include_once( 'class.' . $name . '.php' );
возврат;
>

//ни то, ни другое. попробуем как inc.php
$exists = file_exists ( $tryThis . '/' . $name . '.inc.php' );
if ( $exists )
<
include_once( $name . '.inc.php' );
возврат;
>
>


// не могу найти.
die("Не удалось найти класс $name!");
>
?>

Следующий скрипт проверяет, существует ли файл с таким же именем, и добавляет _n в конец имени файла, где n увеличивается. если img.jpg находится на сервере, он пытается использовать img_0.jpg, проверяет, находится ли он на сервере, и пытается использовать img_1.jpg.
= "изображения/" . $_FILES ['билд']['имя'];
$t = 0 ;
пока( файл_существует ( $img )) $img = "images/" . $_FILES ['билд']['имя'];
$img = substr ( $img , 0 , strpos ( $img , "." )). "_$t" . стрстр($img, ".");
$т++;
>
move_uploaded_file ( $_FILES [ 'bilde' ][ 'tmp_name' ], $img );
?>

При проверке файла, созданного внешней программой в Windows, функция file_exists() не распознает его сразу. Мне кажется, что может потребоваться короткий тайм-аут.

500000) перерыв; // подождите немного
>

if (file_exists($file)) // теперь должно быть надежно
?>

file_exists() уязвим к условиям гонки, а clearstatcache() не позволяет этого избежать.

Следующая функция является хорошим решением:

функция file_exists_safe ( $file ) if (! $fd = fopen ( $file , 'xb' )) return true ; // файл уже существует
>
fclose ( $fd ); // теперь файл создан, нам не нужен обработчик файла
return false ;
>
?>

Функция создаст файл, если нет -existent, последующие вызовы завершатся ошибкой, поскольку файл существует (по сути, это блокировка).

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

функция create_and_lock ($file) if (! $fd = fopen($file, 'xb')) возвращает false;
>
if (! flock ( $fd , LOCK_EX | LOCK_NB )) < // может выйти из строя по другим причинам, LOCK_NB предотвратит блокировку
fclose ( $fd );
отключить ( $file ); // очищаем
возвращаем false ;
>
возврат $fd ;
>

Лучший способ проверить, существует ли файл или каталог в вашем PHP-приложении.

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

Как это лучше всего сделать?

файл_существует

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

  • Если файл (или каталог) существует, возвращается значение true
  • В противном случае будет возвращено значение false

Функция file_exists поддерживается PHP 4, PHP 5, PHP 7 и PHP 8, что означает, что вы можете использовать ее в любом современном приложении PHP, не беспокоясь о совместимости.

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

(Функция clearstatcache, для тех, кто с ней не знаком, очищает кеш статуса файла.)

Использование функции

Чтобы использовать функцию file_exists, вам нужно указать путь к файлу (или каталогу), который вы хотите найти.

Чтобы вывести True или False

Это можно сделать либо путем жесткого кодирования пути в виде строки:

Или передав его функции в качестве параметра:

Передача пути в качестве параметра почти всегда лучше, чем его жесткое программирование в вашей функции.

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

В обоих приведенных выше примерах функция выводит на экран значение true или false в зависимости от результатов.

В условной проверке

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

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

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

Очистка кеша

Как я упоминал в начале этой статьи, результаты функции file_exists кэшируются.

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

Вот как это работает на нашем более простом жестко запрограммированном примере:

Как и следовало ожидать, в нашем более сложном динамическом примере это работает точно так же:

Читайте также: