今回は、PHPで文字エンコーディングを調べたいと思います。文字エンコーディングとは、文字をコンピュータにわかりやすくコードに変換することです。例えば、人間が使う「A」という文字をコンピューターが使う「41」コードに変換して伝えます。
文字エンコードディングをする上で、参照する表、文字コードには、「ASCII」「UTF-8」「シフトJIS」「EUC-JP」などいろいろな種類があります。これがちぐはぐになると文字化けが起こります。例えば、シフトJISで保存したファイルをEUC-JPで開くと人間には判読できない意味不明な文字が表示されてしまいます。
mb_detect_encodingを使う
phpでは、「mb_detect_encoding」という文字エンコーディングを検出する関数があります。これを使って、文字がどんな文字コードなのか調べたいと思いますが、なにやら簡単には行きそうにありません。
php > echo mb_detect_encoding("hello");
ASCII
php > echo mb_detect_encoding("こんにちは");
UTF-8
これって正確?
PHPの文字エンコーディング検出はアテにならない – Qiitaどうやら、mb_detect_encoding
はデフォルトではASCIIとUTF-8しかチェックしてくれないらしいですね。この記事を参考に、PHPがサポートしていて、ひらがながあるだろう文字エンコーディングを、mb_detect_encodingで正しく判別してくれるか確認してみました。
$encording_list = [
"UCS-4",
"UCS-4BE",
"UCS-4LE",
"UCS-2",
"UCS-2BE",
"UCS-2LE",
"UTF-32",
"UTF-32BE",
"UTF-32LE",
"UTF-16",
"UTF-16BE",
"UTF-16LE",
"UTF-7",
"UTF7-IMAP",
"UTF-8",
"ASCII",
"EUC-JP",
"SJIS",
"eucJP-win",
"SJIS-win",
"ISO-2022-JP",
"ISO-2022-JP-MS",
"CP932",
"CP51932",
"SJIS-mac",
"SJIS-Mobile#DOCOMO",
"SJIS-Mobile#KDDI",
"SJIS-Mobile#SOFTBANK",
"UTF-8-Mobile#DOCOMO",
"UTF-8-Mobile#KDDI-A",
"UTF-8-Mobile#KDDI-B",
"UTF-8-Mobile#SOFTBANK",
"ISO-2022-JP-MOBILE#KDDI",
"JIS",
"JIS-ms",
"CP50220",
"CP50220raw",
"CP50221",
"CP50222",
"HTML-ENTITIES"
];
$str = "はじめまして";
foreach ($encording_list as $to_encoding) {
$encoded = mb_convert_encoding($str, $to_encoding, 'UTF-8');
var_dump(
$to_encoding,
$encoded,
mb_detect_encoding($encoded)
);
}
変換する文字コード | 変換された文字 | mb_detect_encoding |
UCS-4 | 0o0X0�0~0W0f | |
UCS-4BE | 0o0X0�0~0W0f | |
UCS-4LE | o0X0�0~0W0f0 | |
UCS-2 | 0o0X0�0~0W0f | |
UCS-2BE | 0o0X0�0~0W0f | |
UCS-2LE | o0X0�0~0W0f0 | |
UTF-32 | 0o0X0�0~0W0f | |
UTF-32BE | 0o0X0�0~0W0f | |
UTF-32LE | o0X0�0~0W0f0 | |
UTF-16 | 0o0X0�0~0W0f | |
UTF-16BE | 0o0X0�0~0W0f | |
UTF-16LE | o0X0�0~0W0f0 | |
UTF-7 | +MG8wWDCBMH4wVzBm- | UTF-7 |
UTF7-IMAP | &MG8wWDCBMH4wVzBm- | UTF-7 |
UTF-8 | はじめまして | UTF-8 |
ASCII | ?????? | UTF-7 |
EUC-JP | �Ϥ���ޤ��� | EUC-JP |
SJIS | �͂��߂܂��� | SJIS |
eucJP-win | �Ϥ���ޤ��� | EUC-JP |
SJIS-win | �͂��߂܂��� | SJIS |
ISO-2022-JP | $B$O$8$a$^$7$F(B | UTF-7 |
ISO-2022-JP-MS | $B$O$8$a$^$7$F(B | UTF-7 |
CP932 | �͂��߂܂��� | SJIS |
CP51932 | �Ϥ���ޤ��� | EUC-JP |
SJIS-mac | �͂��߂܂��� | SJIS |
SJIS-Mobile#DOCOMO | �͂��߂܂��� | SJIS |
SJIS-Mobile#KDDI | �͂��߂܂��� | SJIS |
SJIS-Mobile#SOFTBANK | �͂��߂܂��� | SJIS |
UTF-8-Mobile#DOCOMO | はじめまして | UTF-8 |
UTF-8-Mobile#KDDI-A | はじめまして | UTF-8 |
UTF-8-Mobile#KDDI-B | はじめまして | UTF-8 |
UTF-8-Mobile#SOFTBANK | はじめまして | UTF-8 |
ISO-2022-JP-MOBILE#KDDI | $B$O$8$a$^$7$F(B | UTF-7 |
JIS | $B$O$8$a$^$7$F(B | UTF-7 |
JIS-ms | $B$O$8$a$^$7$F(B | UTF-7 |
CP50220 | $B$O$8$a$^$7$F(B | UTF-7 |
CP50220raw | $B$O$8$a$^$7$F(B | UTF-7 |
CP50221 | $B$O$8$a$^$7$F(B | UTF-7 |
CP50222 | $B$O$8$a$^$7$F(B | UTF-7 |
HTML-ENTITIES | はじめまして | UTF-7 |
UTF-16, UTF-32, UCS2, UCS4 の場合、 エンコーディング検出は常に失敗します。
https://www.php.net/manual/ja/function.mb-detect-order.php
結果
割りかしいけるが、当てにならない。UTF-7になりがち。