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

dari88's diary

これから趣味にするプログラミング/PHP/javascript/kohana/CMS/web design/

おっ、またまた文字化け発見・・・日本語ファイル名をめぐる問題

今日もNetBeansにて「PHP逆引きレシピ」のサンプルコードを教材にPHPの勉強を進めています。

今日は第4章4.2の06.php「ディレクトリ内のディレクトリやファイル名を取得したい」と07-1.php,07-2.php「ディレクトリ内の画像を一覧表示したい」で引っかかりました。日本語のファイルや画像を準備して実行すると文字化けしたり、正常動作しなかったりします。文字化けを見ると思わずニンマリしちゃいます。こういうのは勉強になりますからね。いろいろ試した結果、以下のようなことが分かりました。

<分かったこと>
php.iniの文字コード関係の設定では回避できそうもない。
・Windowsの日本語ファイル名はSJISである。
・サンプルコードは
   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
 でUTF-8を指定しているのだから、SJISのファイル名を叩き出したら文字化けするのが当然。
・mb_convert_encoding()関数を使ってSJISUTF-8の変換を行えば文字化けはなくなる。
 06.phpのfunction h()は次のように書きなおすと良い。

function h($var) { // HTMLでのエスケープ処理をする関数
  if (is_array($var)) {
    return array_map('h', $var);
  } else {
    $var = mb_convert_encoding($var,'UTF-8','SJIS');
    return htmlspecialchars($var, ENT_QUOTES);
  }
}

・サンプルコード07-1.php,07-2.phpが正常動作しない原因は次の文にある。
  $fileName = basename(@$_GET['file']);
 basename()関数がSJISを正しく処理していない模様。そもそもファイル名を渡しているのだから、この処理は深い意味があるのか、そうでもないのか意味不明。
 そこで次のように書きなおすと正常動作する。
  $fileName = @$_GET['file'];
・因みに拾ってきたファイル名をmb_convert_encoding()関数を使ってUTF-8に変換し、urlencode()を行わずに07-2.phpに渡して、再度mb_convert_encoding()関数でSJISに戻すプロセスにしても正常に動作する。

ということで、このサンプルコードは実戦的でとても面白かったです。さて考察なんですけど、公開サーバの場合はSJIS→UTF-8の変換て変ですよね。グローバルな感じじゃない。恐らく漢字とかのファイル名は使わないルールなんじゃないかと思います。