LoginSignup
0
0

More than 3 years have passed since last update.

[PHP]UTF-8で多言語をファイル出力する際に文字化けする

Last updated at Posted at 2020-10-16

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で開くと...
スクリーンショット 2020-10-17 5.08.55.png
こんな感じで文字化けしてしまう。

原因

アプリケーションによって、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);

Excelで開いても、正しく表示されるようになった。
スクリーンショット 2020-10-17 5.35.40.png

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がない場合は表示されない。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0