読者です 読者をやめる 読者になる 読者になる

たきゃはしです

Webとかデザインとかプログラムとか

PHP - ファイル名から拡張子を取得する関数、ベンチマークもあるよ



拡張子取得、それは十人十色の関数である


一般的な拡張子を取得する方法は

  • '.'を区切り文字として配列を作り、最後の要素を取り出す
  • 拡張子があるであろう箇所を正規表現で検索、置換して取得する
  • 最後に出る'.'を検索して以降を抜き出す

など、他にもたくさんあります。


でも、パフォーマンスにバラつきはあるはずだし、
どうせなら「一番いいのを頼む」って考えるのが人の性ってもんですよね


拡張子を取得する関数たち


エントリーNo1
正規表現の関数で配列に分割して最後の要素を取得する

<?php
$filename = '大きい画像a_1010.jpg';
$exts = split("[/\\.]", $filename);
$n = count($exts) - 1;
$ext = $exts[$n];
echo $exts[$n];


エントリーNo2
関数で拡張子を正規表現で検索、置換して取得する

<?php
$filename = '大きい画像a_1010.jpg';
echo preg_replace('/^.*\.([^.]+)$/D', '$1', $filename);


エントリーNo3
関数で配列に分割して最後の要素を取得する

<?php
$filename = '大きい画像a_1010.jpg';
echo end(explode('.', $filename));


エントリーNo4
関数で最後の'.'が現れる場所を取得し、それ以降の文字を取得する

<?php
$filename = '大きい画像a_1010.jpg';
echo substr(strrchr($filename, '.'), 1);


エントリーNo5
関数で'.'を検索し、それ以降の文字を取得する

<?php
$filename = '大きい画像a_1010.jpg';
echo substr($filename, strrpos($filename, '.') + 1);


ベンチマークに使用した関数

<?php
// 対象の関数を10万回処理し、掛かった時間を出力×5
function microtime_float(){
    list($usec, $sec) = explode(" ", microtime());
    return ((float)$usec + (float)$sec);
}
for($i = 0; $i < 5; $i++) {
    $time_start = microtime_float();
    for($j = 0; $j < 100000; $j++){
        // ここに処理を書く
    }
    echo $ext . "\n";
    $time_end = microtime_float();
    $time = $time_end - $time_start;
    echo "time : $time" . "\n";
}

ベンチマーク調査結果

エントリーNo1 - 正規表現で配列に分割して最後の要素を取得する
<?php
$filename = '大きい画像a_1010.jpg';
$exts = split("[/\\.]", $filename);
$n = count($exts) - 1;
$ext = $exts[$n];
echo $exts[$n];
jpg
time : 0.42360711097717
jpg
time : 0.42579102516174
jpg
time : 0.42652201652527
jpg
time : 0.42376804351807
jpg
time : 0.42607593536377

んー!トップバッターなので速いのか分かりません!
続いていきます


エントリーNo2 - 拡張子を正規表現で検索、置換して取得する
<?php
$filename = '大きい画像a_1010.jpg';
echo preg_replace('/^.*\.([^.]+)$/D', '$1', $filename);
jpg
time : 0.30545115470886
jpg
time : 0.30541706085205
jpg
time : 0.30586814880371
jpg
time : 0.30518698692322
jpg
time : 0.30514001846313

おっ!No2がさっそくトップ躍り出た!
しかし、パッと見で何してるのか分からない!笑


エントリーNo3 - 関数で配列に分割して最後の要素を取得する
<?php
$filename = '大きい画像a_1010.jpg';
echo end(explode('.', $filename));
jpg
time : 0.28623914718628
jpg
time : 0.28681802749634
jpg
time : 0.28560900688171
jpg
time : 0.28746509552002
jpg
time : 0.28391718864441

速い!そしてわかり易い!(個人的にだけど。笑
いつもはこれ使ってます!速くて良かった〜


エントリーNo4 - 関数で最後の'.'が現れる場所を取得し、それ以降の文字を取得する
<?php
$filename = '大きい画像a_1010.jpg';
echo substr(strrchr($filename, '.'), 1);
jpg
time : 0.12028694152832
jpg
time : 0.12073612213135
jpg
time : 0.12049007415771
jpg
time : 0.12047910690308
jpg
time : 0.12074589729309

YES!YES!YES! OH MY GOD!
これは速すぎます!群を抜いているッ!


エントリーNo5 - '.'を検索し、それ以降の文字を取得する
<?php
$filename = '大きい画像a_1010.jpg';
echo substr($filename, strrpos($filename, '.') + 1);
jpg
time : 0.118567943573
jpg
time : 0.11897397041321
jpg
time : 0.11767196655273
jpg
time : 0.11784791946411
jpg
time : 0.1175799369812

シャイアーー!

というわけで、最速はエントリーNo5!


「'.'を検索し、それ以降の文字を取得する」でした!

<?php
$filename = '大きい画像a_1010.jpg';
echo substr($filename, strrpos($filename, '.') + 1);


また、今回は可読性より速さを考慮した結果ですので異論はあると思いますが、
そのへんは割愛でお願いします!

  • -

環境
PHP 5.3