忘了什麼時候,我意外的連到國外有一篇文章在談論『PHP取得檔案的副檔名(PHP Get File Extension)』的文章。和我之前的前舊文章「取得檔案的副檔名」相比,那位筆者Cowburn顯然比我認真多了。

Cowburn 把所有取得副檔名的方法都找出來了,而且還評論了哪種方法最適合。果然國外的人寫文章,不會只給答案,還會給過程,看來我寫文章也應該好好學著才行。我先列出Cowburn提到的五種方法,並把其中的註解中文化了。下列的所有方式,最後回傳的結果都是"git"字串,沒有 . 喔!

//假設檔名
$filename = 'mypic.gif';
 
// 1. 使用陣列函式 "explode/end" 方式
$ext = end(explode('.', $filename));
 
// 2. 使用字串函式 "strrchr" 方式
$ext = substr(strrchr($filename, '.'), 1);
 
// 3. 使用字串函式 "strrpos" 方式
$ext = substr($filename, strrpos($filename, '.') + 1);
 
// 4. 使用正規式 "preg_replace" 方式
$ext = preg_replace('/^.*\.([^.]+)$/D', '$1', $filename);
 
// 5. 特別(從來沒用過)方式
//   參考: http://php.about.com/od/finishedphp1/qt/file_ext_PHP.htm
$exts = split("[/\\.]", $filename);
$n = count($exts)-1;
$ext = $exts[$n];

筆者自己使用的方式,是上面的第一種陣列函式,但是使用array_pop()而不是end(),感覺他的用end()似乎更合適。第二、三種字串函式取得法,在其它地方看過別人用過。第四種的正規式…我只能說其實這樣算強了,為了取尾檔名,光想那個正規式就傷我腦了,不過正常來講正規式都滿花費效能的。第五種Cowburn說他從來沒看過,嗯…我也從來沒看過,的確滿特別的。接下來就是Cowburn測試每種的效能,不過他並未將第五種加入比較。以下是各種方式的速度排序由上(快)而下(慢)

  1. 第二種:使用字串函式 "strrchr" 方式
  2. 第三種:使用字串函式 "strrpos" 方式
  3. 第四種:使用正規式 "preg_replace" 方式
  4. 第一種:使用陣列函式 "explode/end" 方式

讓我比較意外的是,使用陣列的方式,效能竟然比正規表達式還要差,囧rz,看來我一開始寫的方式,就是最不好的了。不過在排名上第一位的strrchr的方式還不是最好的,好酒沈甕低!Cowburn首選推薦則是使用pathinfo()這個內建函式

$filename = 'mypic.gif';
$ext = pathinfo($filename, PATHINFO_EXTENSION);

原來官方的內建函式pathinfo(),只要再多給第二參數,就能直接取得所需資料,而且這個方式是全部效能上最好的一個,果然是個好辦法。pathinfo第二參考可傳入的值有:

  • PATHINFO_DIRNAME:取得資料夾路徑
  • PATHINFO_BASENAME:取得整個檔名(主+副)
  • PATHINFO_EXTENSION:取得副檔名
  • PATHINFO_FILENAME :取得主檔名

我們再來補個官方範例會更清楚一點

$path_parts = pathinfo('/www/htdocs/inc/lib.inc.php');

echo $path_parts['dirname'], "\n";
echo $path_parts['basename'], "\n";
echo $path_parts['extension'], "\n";
echo $path_parts['filename'], "\n"; //從PHP 5.2.0開始有

//上面也可以寫這樣
$path = '/www/htdocs/inc/lib.inc.php';

echo pathinfo($path, PATHINFO_DIRNAME), "\n";//return '/www/htdocs/inc'
echo pathinfo($path, PATHINFO_BASENAME), "\n";//return 'lib.inc.php'
echo pathinfo($path, PATHINFO_EXTENSION), "\n";//return 'php'
echo pathinfo($path, PATHINFO_FILENAME ), "\n";//return 'lib.inc' (從PHP 5.2.0開始有)

Cowburn 最後總結,就是建議大家使用pathinfo來取得副檔名,看來以後應該沒什麼異議才對。筆者這邊有一個小插曲,有關於PATHINFO_FILENAME這個在5.2.0推出的新參數。我試著去看他能不能抓到中文檔名,測試結果似乎也是可行的,像是「啦豬賽.png」,但我不小心用到這個字「菊」,像是「菊花開.png」,就會出問題,抓不到(文件已UTF-8編碼過)。原本猜想是不是此函式內部處理是使用ASCII編碼,所以我試著先將字串再轉回為Big5, iconv('UTF-8','Big5',$path),再進行擷取,但是卻變成全亂碼了。所以如果有使用PATHINFO_FILENAME 來抓取主檔案名,還是必需注意一下。

低溫烘培 發表在 痞客邦 PIXNET 留言(1) 人氣()


留言列表 (1)

發表留言
  • p
  • 通常 內建的函式效能都比較好
    我說的是通常
    如果有例外~那就是開發團隊要打屁股
  • PHP官方的內建函式的參考手冊下方,通常都會有很天才的人想出比官方效能更好的寫法,不過我使用的經驗,那些函式通常必需被限制在某種條件情境下,換句話說當處理的數量有不同時,效能就漸漸遜色於官方的了。

    低溫烘培 於 2010/11/08 07:55 回覆