2010-12-15 10 views
24

PHPのpathinfo()関数をUTF-8であることがわかっているファイル名に使用すると、特殊文字の前。ファイル名がUTF-8の場合、PHPのpathinfo()に正しいファイル名を返します。

例:
pathinfo('aä.pdf')リターン:私は期待していたものを、非常にされていない

Array 
(
[dirname] => [the dir] 
[basename] => a.pdf 
[extension] => pdf 
[filename] => a 
) 

Array 
(
[dirname] => [the dir] 
[basename] => aä.pdf 
[extension] => pdf 
[filename] => aä 
) 

罰金とダンディですが、pathinfo('äa.pdf')戻ります。さらに悪い場合は、pathinfo('ä.pdf')が返されます。

Array 
(
[dirname] => [the dir] 
[basename] => .pdf 
[extension] => pdf 
[filename] => 
) 

なぜこれはですか?これは私がテストしたすべてのアクセント記号付きの文字になります。

+3

ほとんどのコアPHP関数は、ISO-8859-1(Latin-1の)以外に設定します。実際の選択肢は、マルチバイト文字セットセーフ機能( 'mb_string'関数)を使用して自分で関数を再実装することだけです。 – ircmaxell

+1

PHPのどのバージョンを実行していますか? – ajreal

+0

@ajrealそれはDebian lennyのPHP 5.2.6-1 + lenny9です – Zsub

答えて

7

一時的な回避策はそうのように、アクセント付き文字の前に「通常」の文字があることを確認するように見えます/ 'with a'/a 'しかし、結果のオフセット1から始まるので、これは問題ありません。面白いことに、dirnameの部分がpathinfo()のように見えるので、回避策は必要ありません。

+2

これはまだ2016年のバグですが、 'setlocale(LC_ALL、 'en_US.UTF-8');は動作します。 – Drakes

5

pathinfo() cannot handle argument with special characters like german 'Umlaute'」を参照してください。私たちは "の出現をすべて置き換える

function getFilename($path) 
{ 
    // if there's no '/', we're probably dealing with just a filename 
    // so just put an 'a' in front of it 
    if (strpos($path, '/') === false) 
    { 
     $path_parts = pathinfo('a'.$path); 
    } 
    else 
    { 
     $path= str_replace('/', '/a', $path); 
     $path_parts = pathinfo($path); 
    } 
    return substr($path_parts["filename"],1); 
} 

注:この問題の

+0

http://php.net/ChangeLog-5phy – ajreal

+0

このバグは、UTF-8文字ではなくASCII以外の文字に関連しています。だから、100%適用可能かどうかは分かりません(-1であるかもしれませんが、非常に古いバグなので根本的な原因ではないと確信しています)。 – ircmaxell

+0

@ircmaxell My characters indeed少なくともUTF-8であるべきです。つまり、私のロケールはUTF-8で、.phpファイルはUTF-8として保存されます。私は自分のロジックを使うためにpathinfo()を使って関数を書き直すつもりだと思いますが、それは 'meh'のようなものです。 – Zsub

9

私はbasename()とpathinfo()でUTF-8の問題を処理するためにPHP 5.3.3 - 5.3.18でこれらの関数を使用しています。

 

if (!function_exists("mb_basename")) 
{ 
    function mb_basename($path) 
    { 
    $separator = " qq "; 
    $path = preg_replace("/[^ ]/u", $separator."\$0".$separator, $path); 
    $base = basename($path); 
    $base = str_replace($separator, "", $base); 
    return $base; 
    } 
} 
 
if (!function_exists("mb_pathinfo")) 
{ 
    function mb_pathinfo($path, $opt = "") 
    { 
    $separator = " qq "; 
    $path = preg_replace("/[^ ]/u", $separator."\$0".$separator, $path); 
    if ($opt == "") $pathinfo = pathinfo($path); 
    else $pathinfo = pathinfo($path, $opt); 

    if (is_array($pathinfo)) 
    { 
     $pathinfo2 = $pathinfo; 
     foreach($pathinfo2 as $key => $val) 
     { 
     $pathinfo[$key] = str_replace($separator, "", $val); 
     } 
    } 
    else if (is_string($pathinfo)) $pathinfo = str_replace($separator, "", $pathinfo); 
    return $pathinfo; 
    } 
} 
1

プロセスのANSI文字は、関数パス情報を正しく行います。

これは、入力をansi charatersに変換(エンコード)してから、引き続き関数pathinfoを使用して全体の状態を維持することを目的としています。

最後に、出力値を元の形式に変換(デコード)します。

次のようにデモしてください。文字に対処していない、使用前に

function _pathinfo($path, $options = null) 
{ 
    $path = urlencode($path); 
    $parts = null === $options ? pathinfo($path) : pathinfo($path, $options); 
    foreach ($parts as $field => $value) { 
     $parts[$field] = urldecode($value); 
    } 
    return $parts; 
} 
// calling 
_pathinfo('すtest.jpg'); 
_pathinfo('すtest.jpg', PATHINFO_EXTENSION); 
6

パス情報
setlocale(LC_ALL,'en_US.UTF-8'); 
pathinfo($OriginalName, PATHINFO_FILENAME); 
pathinfo($OriginalName, PATHINFO_BASENAME); 
+2

説明とドキュメントへのリンクを追加すると、元のポスターや他のユーザーが実際にそれから学ぶことができるので、答えはより価値が高くなります。 –

+0

この回答は役に立ちましたし、それは簡単です。他の人に価値を高めるために説明を追加してください。 – Drakes

+0

説明があります:https://stackoverflow.com/questions/45268499/php-basename-and-pathinfo-with-multibytes-utf-8-file-names/45268539#45268539 –

0
private function _pathinfo($path, $options = null) { 
    $result = pathinfo(' ' . $path, $options); 
    return substr($result, 1); 
} 
関連する問題