[PHP]UTF-8で多言語をファイル出力する際に文字化けする
PHPでUTF-8で中国語をテキストファイルに出力すると、開くアプリケーションによって文字化けが起こる事象に遭遇した。
元のプログラム
<?php
$filePath = 'mojibake.txt';
$value = '你好';
$fh = fopen($filePath, 'w');
fwrite($fh, mb_convert_encoding($value, 'UTF-8'));
fclose($fh);
途中の処理は省略している。
$ cat mojibake.txt
你好%
ちゃんと出力されているし、Macのテキストエディタで開いても正しく表示される。しかしこれをExcelで開くと...
こんな感じで文字化けしてしまう。
原因
アプリケーションによって、Unicodeの符号化方式が判別できず、UTF-8・UTF-16・UTF-32を判別できないため、文字化けが起きてしまう。
解決策
上を判別させるために、ファイル出力時の先頭にBOMをつける。
BOMとは
BOMとは、Byte Order Markの略称で、Unicodeの符号化方式を判別するために、ファイルの先頭につける数バイトのマーク。
プログラムがテキストデータを読み込む時、その先頭の数バイトからそのデータがUnicodeで表現されていること、また符号化形式(エンコーディング)としてどれを使用しているかを判別できるようにしたものである。
バイトオーダーマーク - Wikipedia
BOMは以下の通り。
符号化形式 | エンディアンの区別 | BOM |
---|---|---|
UTF-8 | 0xEF 0xBB 0xBF | |
UTF-16 | BE | 0xFE 0xFF |
UTF-16 | LE | 0xFF 0xFE |
UTF-32 | BE | 0x00 0x00 0xFE 0xFF |
UTF-32 | LE | 0xFF 0xFE 0x00 0x00 |
今回はUTF-8なので、0xEF 0xBB 0xBF
を先ほどのファイルの先頭につけるようにする。
修正したプログラム
<?php
$filePath = 'mojibake.txt';
$value = '你好';
$fh = fopen($filePath, 'w');
// add BOM
fwrite($fh, "\xEF\xBB\xBF");
fwrite($fh, mb_convert_encoding($value, 'UTF-8'));
fclose($fh);
BOM付かどうかファイル情報を調べる
ファイルにBOMが付いているかはコマンドで調べることができる。
$ file mojibake.txt
mojibake.txt: UTF-8 Unicode (with BOM) text, with no line terminators
BOMが付いているとwith BOM
と表示される。
$ file mojibake2.txt
mojibake2.txt: UTF-8 Unicode text, with no line terminators
BOMがない場合は表示されない。
Author And Source
この問題について([PHP]UTF-8で多言語をファイル出力する際に文字化けする), 我々は、より多くの情報をここで見つけました https://qiita.com/vetra/items/b4c57342823371bf3103著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .