と言うわけで、久しぶりにはまってしまったのでちょっと書いてみます。
Webプログラムをテキストエディタで行うときにはそのエディタの特性に要注意
OS付属のメモ帳からフリーのエディタ、シェアのエディタ、VisualStudioのような統合型のエディタなどいろいろとありますが、そのエディタの特性は知っておかないといろいろと大変だったりします。
この場合の特性とは、それぞれのプログラム言語上で使いやすいか、ではなく文字コードの扱いをどうするかにあります。
エディタの文字コードについては
- 扱うことができる文字コードの種類(特に現在のエディタであればUTF-8は必須。ShiftJIS、EUC、UTF-16もあった方がいい)
- BOM(Byte Order Mask。この場合はファイル先頭にある文字コードを示すバイトコード)をどうするか
- 文字コードの自動認識の扱い
にあります。
UTFとBOM
初めに書いておくと、メモ帳でUTF系の文字コードで保存すると自動的にBOMがつきます。これがものすごい問題に。
また、汎用的なテキストエディタではUTFのBOMは「つけることもつけないこともできる」物が多いと思います。
Webプログラム言語専用のテキストエディタの場合は「だいたいBOMはつけない」物が多いと思います。
これはUnix系列での文字コードはASCIIを基本としているため、それと互換を持つBOMなしUTF-8を用いることが多くなっているためです。
なので、BOMがあったときに「文字コードを認識後無効化する」ことは基本的にせず、「もとからASCII(というかUTF-8)として扱うのでそのままBOMが残る」と言う現象が起こります。
phpなどのプログラムではこれが致命的なことに
Unix系のShellでも似たようなことが起こることがありますが、php系の方が影響が大きいです。
php系で間違えてBOMが入ったコードが実行されるとその時点でBOMが出力バッファに入ってしまうことにあります。
そのため、たとえば画像を出力するときに画像のバイナリデータの前にBOMがバイナリデータとして添付されてしまい、ブラウザで画像が壊れてしまう、と言うことも起こります。
Shellの場合は単純にファイルの先頭に書いてあるシェルプログラムの指定を正しく読み込むことができなくて実行できない、と言うパターンです。まだファイルが特定できるだけましです。
ファイルのバイナリデータ検索が必要?
と言うことも起こります。一応邪道ですが対応策があり、最終出力がhtml文章となるときだけ有効ですが、出力が開始される前にob_clean関数を呼び出して出力バッファをクリアしてしまう、と言う方法があります。
ContentTypeの設定が必要なときはこの方法が使えないのが残念ですが。(BOMが出力された時点でContentTypeがtext/htmlになってしまうため)
その場合は頑張ってBOMがついているファイルを探すか、UTF-8のBOMなしに変換できるファイルの文字コード変換プログラムを通すなりしてどうにかしてください。