mb_detect_encoding

文字エンコーディングを検出する

説明

stringfalse mb_detect_encoding(string $string, arraystringnull $encodings = null, bool $strict = false)

エンコーディングの候補の一覧から、 文字列 string のもっとも可能性が高い文字エンコーディングを検出します。

PHP 8.1 以降では、 この関数は指定されたテキスト中の有効なテキストエンコーディングのうち、 もっとも正しい可能性が高いものを、経験則を用いて検出します。 そのため、encodings の順番通りでない場合があります。 

追加の情報なしに、 意図した文字エンコーディングを自動で検出する行為は、 全く役に立ちません。 これは、暗号化された文字列を鍵なしにデコードする行為に似ています。 "Content-Type" HTTP ヘッダのような、 データを転送された際に付いてくる情報や、 保存された文字エンコーディングに関する指示を指定することが常に望ましいです。

この関数は、全ての文字列が正しいバイト配列とは限らない マルチバイト文字列を指定するともっとも役に立ちます。 入力となる文字列に誤ったバイトが含まれていた場合、 そのエンコーディングは採用されません。

警告

この関数の結果は正確ではありません

この関数の名前は誤解を招きやすいです。 この関数は 「検出」(detection) ではなく 「推測」"guessing" を行います。

この関数が行う「推測」は正確には程遠いので、 正しい文字エンコーディングを検出する用途に、この関数は使えません。

パラメータ

string

調べる対象の文字列。

encodings

試す文字エンコーディングの一覧を指定します。 このリストは、文字列の配列または、 カンマ区切りのリストで指定できます。

encodings が省略された場合、 または null の場合、 現在の detect_order ( mbstring.detect_order 設定オプション または mb_detect_order で設定したもの) を使います。

strict

encodings で指定された 文字エンコーディングのリストの全てに対して、 不正と判定された場合の振る舞いを指定します。 strictfalse の場合、 もっとも近いと判定された文字エンコーディングが返されます。 stricttrue にした場合、 false が返されます。

strict のデフォルト値は mbstring.strict_detection 設定オプションで指定できます。

戻り値

検出した文字エンコーディングを返します。 指定したエンコーディングの全てに対して、不正と判定された場合は false を返します。

変更履歴

バージョン 説明
8.2.0 mb_detect_encoding は、 以下のテキストでないエンコーディングを返さなくなりました: "Base64", "QPrint", "UUencode", "HTML entities", "7 bit", "8 bit"

例1 mb_detect_encoding の例

<?php

$str = "\x95\xB6\x8E\x9A\x83\x52\x81\x5B\x83\x68";

// 現在のdetect_orderで文字エンコーディングを検出
var_dump(mb_detect_encoding($str));

// "auto" は mbstring.language の設定を使って展開されます
var_dump(mb_detect_encoding($str, "auto"));

// 文字エンコーディングをカンマ区切りのリストで指定することで、encodings 引数を指定
var_dump(mb_detect_encoding($str, "JIS, eucjp-win, sjis-win"));

// encodings 引数を配列で指定
$encodings = [
  "ASCII",
  "JIS",
  "EUC-JP"
];
var_dump(mb_detect_encoding($str, $encodings));
?>

上の例の出力は以下となります。

string(5) "ASCII"
string(5) "ASCII"
string(8) "SJIS-win"
string(5) "ASCII"

例2 strict パラメーターの効果

<?php
// 'áéóú' は ISO-8859-1 でエンコードされています
$str = "\xE1\xE9\xF3\xFA";

// この文字列は、ASCII または UTF-8 的には正しくありませんが、
// UTF-8 がもっとも近いと判定されます
var_dump(mb_detect_encoding($str, ['ASCII', 'UTF-8'], false));
var_dump(mb_detect_encoding($str, ['ASCII', 'UTF-8'], true));

// 正しいエンコーディングが見つかった場合、
// strict パラメータを指定しても結果は変わりません
var_dump(mb_detect_encoding($str, ['ASCII', 'UTF-8', 'ISO-8859-1'], false));
var_dump(mb_detect_encoding($str, ['ASCII', 'UTF-8', 'ISO-8859-1'], true));
?>

上の例の出力は以下となります。

string(5) "UTF-8"
bool(false)
string(10) "ISO-8859-1"
string(10) "ISO-8859-1"

場合によっては、同じバイト配列が、 複数の文字エンコーディング的に正しいかもしれませんが、 どの解釈が意図されたものなのかを知ることは不可能です。 たとえば、 バイト配列 "\xC4\xA2" は、 以下のように解釈できます:

  • "Ä¢" (U+00C4 LATIN CAPITAL LETTER A WITH DIAERESIS のあとに、U+00A2 CENT SIGN が続いたもの) これらは、ISO-8859-1, ISO-8859-15, Windows-1252 でエンコードされたものと解釈できます。
  • "ФЂ" (U+0424 CYRILLIC CAPITAL LETTER EF のあとに、 U+0402 CYRILLIC CAPITAL LETTER DJE が続いたもの) これは、ISO-8859-5 でエンコードされたものと解釈できます。
  • "Ģ" (U+0122 LATIN CAPITAL LETTER G WITH CEDILLA) これは、UTF-8 でエンコードされたものと解釈できます。

例3 複数のエンコーディングと一致した場合の効果

<?php
$str = "\xC4\xA2";

// 3つ全てのエンコーディングに照らして正しい文字列ですが、
// 最初のひとつが常に返されるとは限りません
var_dump(mb_detect_encoding($str, ['UTF-8']));
var_dump(mb_detect_encoding($str, ['UTF-8', 'ISO-8859-1', 'ISO-8859-5'])); // PHP 8.1 以降では、UTF-8 ではなく ISO-8859-1 が返されます
var_dump(mb_detect_encoding($str, ['ISO-8859-1', 'ISO-8859-5', 'UTF-8']));
var_dump(mb_detect_encoding($str, ['ISO-8859-5', 'UTF-8', 'ISO-8859-1']));
?>

上の例の出力は以下となります。

string(5) "UTF-8"
string(10) "ISO-8859-1"
string(10) "ISO-8859-1"
string(10) "ISO-8859-5"

参考

  • mb_detect_order