私のパソコン雑記帖

UTF-8 関連

カテゴリー: PHP
20Aug2009

UTF-8 BOM の問題

BOM (Byte Order Mark) の専門的な説明は他に譲りたいと思いますが、UTF-8 でコーディングする場合、ファイルの先頭に BOM が付く場合と付かない場合があります。BOM は efbbbf の3バイトが付与されます。例えば Windows のメモ帳で作成したドキュメントを UTF-8 形式で保存すると、BOM が付きます。このことを理解していないと思わぬトラップにはまることがあります。

次のようなドキュメント(3行の文字列)をメモ帳で作ったとします。UTF-8 エンコーディング。ファイル名を sample.txt とします。

2eee
bbb
3bbb

この sample.txt に対して次のコードを実行します。

$f=file("sample.txt");
sort($f);
print_r($f);

この結果は

Array ( [0] => 3bbb [1] => bbb [2] => 2eee )

となり、BOM が結果に影響していることがわかります。次に BOM を取り除くコードを追加して実行します。

$f=file("sample.txt");
if(substr(bin2hex($f[0]),0,6)=="efbbbf"){$f[0]=substr($f[0],3);} //delete BOM if any.
sort($f);
print_r($f);

この結果は

Array ( [0] => 2eee [1] => 3bbb [2] => bbb )

となり、BOM が取り除かれたことがわかります。このように BOM の有無が影響する可能性があるときは、それを除去しておかないと思わぬ結果を招きます。上記例は私が実際悩んだケースから抽出しました。


UTF-8 の文字数

strlen(): マルチバイト文字は3文字分とカウントされる。(euc-jp や shift_jis 等では2文字分とカウントされる。)
mb_strlen(): マルチバイト文字もシングルバイト文字も1文字とカウントされる。
mb_strwidth(): マルチバイト文字はシングルバイト文字の倍の幅にカウントされる。

mb_internal_encoding("UTF-8");
$str = "abcあいう";


print strlen($str);

結果: 12

print mb_strlen($str);

結果: 6

print mb_mb_strwidth($str);

結果: 9



参照
文字列の幅を返す PHP: mb_strwidth - Manual
指定した幅で文字列を丸める PHP: mb_strimwidth - Manual



コメント