Windows版PHPで日本語ファイル名が正しく扱えない問題について

2016-10-17

#PHP

Windows 版の PHP(5.3~7.0) では、日本語等の全角文字(非ASCII文字)を含むファイル名の取得や指定に失敗することがあります。
例えば glob()scandir()RecursiveDirectoryIterator などのイテレータを使ってファイル名一覧を取得した時、一部のファイルが抜け落ちてしまいます。

原因

原因はどうやら二つあるようです。
一つは、Windows 版 PHP は Shift_JIS でファイル名を扱うようで、Unicode を含むファイル名を無視してしまう為です。
もう一つは、いわゆる 5c 問題です。Shift_JIS では全角文字の2バイト目が \ 記号 (0x5c, バックスラッシュ) を含むことがあり、これがエスケープ文字やディレクトリ名の区切りと誤認識されてしまう事に起因する不具合です。

解決策

これに対する解決策はないかと、様々試行錯誤してみたのですが解決できませんでした。
glob() を使ってもイテレータを使ってもダメだったので、setlocale(LC_ALL, 'Japanese_Japan.932')mb_internal_encoding('CP932') 等で 5c 問題だけでも解決するかもしれないと思い試してみましたが、こちらもダメでした。
よって、Windows 版 PHP(5.3~7.0) では非ASCII文字のファイル名を全て正しく扱うことは残念ながら出来ないというのが結論です。

ただ、色々調べていて解ったことがあります。
実は、PHP5.2 までは (恐らく 5c 問題については) 大丈夫だったようなのです。
つまりこれは、PHP5.3 以降、PHP7.0 までに固有のバグだということです。
更にこちらの記事によれば、このバグは PHP7.1 で遂に修正され、喜ばしいことに Shift_JIS の 0x5c や Unicode を含むファイル名も UTF-8 で正しく扱えるようになるとの事です!やったー(´;ω;`)ウッ…

サーバ運用では日本語ファイル名をどうしても扱わなければならないケースというのはあまり無いとは思いますが、やはり正しく扱えれば有り難い事ですね。

テスト環境

PHP 5.6.15, Windows 10

参考

QooQ