Расширение файла средствами PHP

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

    Считаете, что вопрос пустяковый и все тут просто как 2 пальца? Может быть, только недавно мне встретилась занятная бредострочка с толстенным регулярным выражением и все для того, что бы просто получить несколько символов в конце строки после последней точки. Зачем? Итак, начнем с пяти наиболее распространенных способов. Без использования регулярных выражений (только не подумайте, что я считаю их злом). Писать буду как просто и доступно, это не научная статья, а авторская заметка.

    Способ первый
    1.   function getExtension1($filename) {
    2.     return end(explode(".", $filename));
    3.   }
    Логика такова: используя функцию explode(), полученная строка преобразуется в массив строк, границами которых в оригинале был разделитесь «точка». И все бы хорошо, если речь идет об имени файла в стиле «file.txt», но как быть если точек несколько? Для этого end() возвращает последний элемент массива, т.е. то, что было после последней точки.

    Способ второй
    1.   function getExtension2($filename) {
    2.     $path_info = pathinfo($filename);
    3.     return $path_info['extension'];
    4.   }
    Здесь на помощь приходит функция pathinfo(), которая возвращает ассоциативный массив, содержащий информацию о нужном нам файле. И если ваша задача узнать не только расширение файла, а так же полный путь к нему и полное имя файла, то этот способ для вас: массив, возвращаемый данной функцией, содержит элементы dirname, basename и extension — в них вся нужная информация.

    Способ третий
    1.   function getExtension3($filename) {
    2.     return substr($fileName, strrpos($fileName, '.') + 1);
    3.   }
    В данном случае strrpos() возвращает позицию последней точки в строке, а substr() вырезает все символы, начиная с полученной ранее позиции точки, до конца строки. Что бы избавится от самой точки в полученной подстроке, мы увеличивает начало старта на одно смещение вправо (+1).

    Способ четвертый
    1.   function getExtension4($filename) {
    2.     return substr(strrchr($fileName, '.'), 1);
    3.   }
    Работает следующим образом: strrchr() возвращает участок строки, следующий за указанным параметром (точкой в нашем случае), после чего substr() отрезает первый символ — точку.

    Способ пятый
    1.   function getExtension5($filename) {
    2.     return array_pop(explode(".", $filename));
    3.   }
    Данный способ очень похож на первый. array_pop() — выталкивает элемент в конце массива, end() — устанавливает внутренний указатель массива на последний элемент.

    Что работает быстрее? Да, в прочем, на практике результаты выполнения и всех способов примерно одинаковые. Для подтверждения своих догадок провел небольшой тест, прогнав в цикле каждый из вариантов по 50000 раз:
    Способ #1: 0.6777439 сек.
    Способ #2: 0.5664740 сек.
    Способ #3: 0.6604638 сек.
    Способ #4: 0.4782789 сек.
    Способ #5: 0.6564250 сек.

    Какой использовать? Решать вам.
    Поделиться публикацией

    Похожие публикации

    Комментарии 66

      0
      из всего предложенного, мне как-то более близок #1, хотя кому как — на способы реализации товарищей нет
        0
        я бы подумал сколько действий выполнится в 1 случае и откинул бы сразу, выглядит он как-то вроде мы трактором копаем червей для рыбалки.
        –4
        Использую третий способ, но спасибо за тест!
          0
          На мой взгяд это самый бесполезный тест, причем результаты отличаются всего на 0,1 сек. Но по перечисленным способам претензий не имею.
            +1
            Не отрицаю, но сделал его во избежании комментариев с утверждением того, что тот или иной метод в разы быстрее. Я лишь подтвердил, что способы равнозначны.
              0
              >причем результаты отличаются всего на 0,1 сек.
              на 0.1сек. на 50000-кратном цикле :)
              +10
              В третьем и четвертом примерах опечатки (аргумент $filename, а в теле функции используются $fileName).

              Ради интереса протестировал все функции с именами файлов, которые
              а) не содержат расширения (file)
              б) имя файла с путем, в котором есть расширение (/path.dir/file.ext)
              в) имя файла без расширения с путем, в котором есть расширение (/path.dir/file)

              Результаты:
              а)
              1 'file'
              PHP Notice: Undefined index: extension in /tmp/test_ext.php on line 9
              2 ''
              3 'ile'
              4 ''
              5 'file'

              б)
              1 'ext'
              2 'ext'
              3 'ext'
              4 'ext'
              5 'ext'

              в)
              1 'dir/file'
              PHP Notice: Undefined index: extension in /tmp/test_ext.php on line 9
              2 ''
              3 'dir/file'
              4 'dir/file'
              5 'dir/file'

              Выводы:
              Если не обращать внимание на notice, то второй способ сработал нормально во всех случаях. Notice устраняется проверкой результата с помощью isset(). Все остальные способы можно использовать с осторожностью. 4й способ дает правильный результат при отсутствии пути (или как минимум точек в пути)
                0
                Предложу еще один testcase — файл .htaccess. По моему скромному мнению, в данном случае «.htaccess» — это все же имя файла; pathinfo() из второго способа считает, что это файл без имени, но с расширением. Странно это все.
                –4
                мне ближе второй способ. Не ожидал что по такой задаче можно тесты делать.
                  0
                  Лабораторка для первого курса…
                  Давайте еще напишем статью про 10 способов объявить и инициализировать переменную.
                    –1
                    А я где-то написал, что это мой научный труд?
                    P.S. Давайте. Инициализация переменной важный и обязательный момент.
                    0
                    а как быть в таких случаях?
                    file
                    file.with.extension
                    .itsfiletoo
                    readme-1.10.0.384_rev2.392.11
                      +17
                      pathinfo($fileName, PATHINFO_EXTENSION);

                      ? o_O
                        –4
                        Только сам об этом подумал. Думаю это оптимальный вариант.
                          0
                          Иногда люди черезмерно увлекаются написанием собственных каркасов и т. п. возвышаясь в своих глазах и совершенно не подозревая что изобретают велосипед. Просто прочитайте справочник по функциям и вы откроете для себя много нового ранее не виданного и интересного, особенно обратите внимание на функции для работы со строками.
                            0
                            Да! :)
                            +2
                            pathinfo($file, PATHINFO_EXTENSION);
                              0
                              впринципе итак понятно что строковые функции будут самыми быстрыми :) а вообще коофициент полезности такого теста стремится к нулю. ну и как ораторы выше меня уже сказали решения не избавлены ошибок.
                                –13
                                preg_match(«!\.(\w+)$!», $file, $path);
                                return $path[1];
                                  0
                                  опс, ошибку понял: \w сюда не подходит.
                                    0
                                    вы пытаетесь из пушки по мухам стрелять
                                    +1
                                    function getExtension6($filename) {
                                    return preg_replace('/^.*\.(.*)$/U', '$1', $filename);
                                    }

                                    function getExtension7($filename) {
                                    return preg_match('/\.(.*)$/U', $filename, $matches)? $matches[1]: '';
                                    }

                                    1: 0.34617495536804
                                    2: 0.39701700210571
                                    3: 0.19387984275818
                                    4: 0.14295220375061
                                    5: 0.31544399261475
                                    6: 0.56111097335815
                                    7: 0.59882402420044

                                    Вот и результат :) Не ожидал, что регулярки себя так плохо покажут…
                                      0
                                      а что если упростить регулярки?
                                      '/\.(.*)$/'
                                      может скорости прибавит?
                                        +1
                                        Время уходит не на обработку регулярных выражений, а на их компиляцию. Вот если бы у вас имя файла содержало миллионы символов — можно было бы увидеть разницу…
                                          –7
                                          Использовал скомпилированные (/S) врем'я сильно не отличалось почемуто, да там были реальные файлы а не повтор на одном файле, потому експеримент чист!
                                            +1
                                            Всем минусовальщикам спасибо, вы заминусовали вывод из реального експеримента, а новички посчитают что вы все молодцы, а я дурак. Они вам спасибо не скажут.
                                            0
                                            Вот результат скомпилированной:
                                            1: 0.31407904624939
                                            2: 0.4003050327301
                                            3: 0.19335794448853
                                            4: 0.14210796356201
                                            5: 0.3144679069519
                                            6: 0.53428292274475
                                            7: 0.59622716903687
                                            0
                                            В getExtension6 нельзя упрощать регулярку, потому как получим мусор (нужна замена всей строки)
                                            0
                                            Результат предсказуем. Какой… не будем говорить кто придумал для PHP регулярные выражения, которые невозможно компилировать — хотелось бы узнать. Регулярные выражения при разборе шаблона строят конечный автомат — это медленно и сложно. К тому же эта часть кода не очень вылизана. А зато вот потом поиск с использованием регулярных выражений происходит мгновенно. Любой нормальный человек скажет что компиляцию регулярных выражений нужно делать один раз, а использовать — столько, сколько нужно. Но в PHP эти две операции объединены в одну!
                                              0
                                              '/..../S' — компилируемая регулярка (RTFM)
                                                0
                                                и где ее, простите, хранить ?!
                                                чтобы заюзать хотя-бы дважды?
                                                  –3
                                                  Это уже проблема PHP, в ньом всьо так реализовывается.
                                                  Когдато тестил эту фишку, она действительно работает, но сейчас почемуто не дала результата. Возможно данных много в памяти, я же в скрипт вонал «маленький» масивчик всего то 5 Мб
                                                    0
                                                    Это уже проблема PHP, в ньом всьо так реализовывается.

                                                    khim вам то же самое сказал, а вы ему — RTFM ;)
                                                    компилируемые регулярки в PHP загадочны, и в этом их минус. в остальном PCRE неплох, хотя до .NET-овских ему было бы очень неплохо «подрасти» ибо в них есть очень приятные бонусы которых в PCRE пока нема :(
                                                      0
                                                      соррі, khim.
                                                      Загадочность не значит «плохо» :)
                                                      Не знаю как на счет .NET, а Java дает полный контроль… Но для меня синтаксиса PCRE вполне достаточно (в Java он шыре)
                                              0
                                              Есть программа визуально показывающая процесс работы регулярного выражения для определенной строки… там все станет намного понятней, к сожалению названия не помню но стать тут про нее была.
                                                +1
                                                The Regex Coach — одна из таких программ.
                                              +4
                                              Осталось придумать такую задачу, в которой нужно будет на PHP получить расширение у 50000 файлов ;)
                                                0
                                                Дельное замечание ;)
                                                  0
                                                  Приведу реальный пример, с которым я столкнулся.

                                                  Есть огромный архив файлов, который содержит миллионы файлов. Мне нужно было дергать в БД, только те файлы, у которых разрешение было *.bz2 (разрешение может меняться в зависимости от настроек). Вот вам и реальный пример.
                                                  • НЛО прилетело и опубликовало эту надпись здесь
                                                      0
                                                      И при этом сделать это нужно именно на PHP? :) А что касается экономичности вашего решения, то SelenIT хорошо расписал. Скорость определения расширения будет явно не самой критичной в вашем случае и оптимизировать её не нужно.
                                                      0
                                                      Обойдемся без задачи :) Тест был исключительно для нанооптимизаторов, что бы в их мозгу отложилось «строковые функции быстрее регулярных выражений».
                                                        0
                                                        Тогда вы и сами должны понимать, что это не самый лучший пример для них :)
                                                      +1
                                                      Второй способ.
                                                      Остальное велосипеды…
                                                        –9
                                                        второй самый тормозный… :)
                                                          0
                                                          Зато самый верный
                                                            –2
                                                            Такой критерий работает в маленьких сайтиках, а высоконагруженные системы такого не терпят, — прийдется перекрывать железом…
                                                            0
                                                            Спасибо всем за минусы — за правду всегда бить будут ;)

                                                            В компилированом варианте регулярок который провел я в habrahabr.ru/blogs/php/37753/#comment_887934 все подтвердилось.

                                                            ну да ладно… че я тут борец за справедливость? ;)
                                                        • НЛО прилетело и опубликовало эту надпись здесь
                                                          • НЛО прилетело и опубликовало эту надпись здесь
                                                              –10
                                                              это ты про свой камент?
                                                              –3
                                                              мде, а если у файла екст док. а а он докХ,
                                                              или например екст гиф, а он жипег,
                                                              или вообще ект. нету? :-/
                                                                0
                                                                поэтому надо использовать mime, например чере fileinfo.
                                                                  –13
                                                                  Незря кто-то говорил, что карма нужна про запас, или для защиты от всяких хабра-пидаров!
                                                                  В топике показаны фунции обработки строк (и сравениние их работы по времени) но не работы с расширением файлов. И минус влепили низахуй опять! Быдла на хабре полно, еще и в карму срет.
                                                                    –8
                                                                    Мде… no comments
                                                                    ps: пидары — здохнуте от спида
                                                                    • НЛО прилетело и опубликовало эту надпись здесь
                                                                      • НЛО прилетело и опубликовало эту надпись здесь
                                                                    +3
                                                                    Господа, вы бесповоротно рехнулись.
                                                                    Если вам критично выполнение простейшей строковой функции, то почему бы на ассемблере не писать?
                                                                    Что будет дальше? Будем мерять скорость сложения простых чисел? Или сравнивать скорости смены знака способом ($i = -$k) и ($i = $k * -1)?
                                                                    Вы меня извините, конечно, но считаю саму статью маразматичной, не говоря уже о столь серьезном ее обсуждении.
                                                                      +7
                                                                      В root мне логи! А я как последний дурак тратил на 0,000003643698 секунды больше, используя третий вариант :(
                                                                        +4
                                                                        Фига себе нанооптимизаторы мне карму снесли :) Теперь придется долго реабилитироваться в комментариях опусами о влиянии регистра букв в переменных на производительность скрипта :)
                                                                        • НЛО прилетело и опубликовало эту надпись здесь
                                                                            0
                                                                            Я в разных дискуссиях участвую и моя карма тоже прыгает как кардиограмма :) +4 в карму
                                                                            0
                                                                            Только никому не говорите, а то сочтут вас неквалифицированным ;)
                                                                            0
                                                                            Автор, добавь еще 3 способа упомянутых в коментариях, с делай нормальную таблицу сравниния :)
                                                                            Будем очень благодарны ;)
                                                                              0
                                                                              регулярные выражения нынче не в моде?
                                                                                0
                                                                                Я тоже раньше использовал третий, но четвертый мне тоже понравился ;)

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

                                                                                Самое читаемое