質問

いくつかのテキストのエンコード(PHPを使用)を検出したいと思います。そのために、私はmb_detect_encoding()関数を使用します。

問題は、MB_DETECT_ORDER()関数を使用して可能なエンコーディングの順序を変更すると、関数が異なる結果を返すことです。

次の例を考えてください

$html = <<< STR
ちょっとのアクセスで落ちてしまったり、サーバー障害が多いレンタルサーバーを選ぶとあなたのビジネス等にかなりの影響がでてしまう可能性があります。特に商売をされている個人の方、法人の方は気をつけるようにしてください
STR;
mb_detect_order(array('UTF-8','EUC-JP', 'SJIS', 'eucJP-win', 'SJIS-win', 'JIS', 'ISO-2022-JP','ISO-8859-1','ISO-8859-2'));
$originalEncoding = mb_detect_encoding($str);
die($originalEncoding); // $originalEncoding = 'UTF-8'

ただし、mb_detect_order()でエンコーディングの順序を変更すると、結果は異なります。

mb_detect_order(array('EUC-JP','UTF-8', 'SJIS', 'eucJP-win', 'SJIS-win', 'JIS', 'ISO-2022-JP','ISO-8859-1','ISO-8859-2'));        
die($originalEncoding); // $originalEncoding = 'EUC-JP'



だから私の質問は次のとおりです。
なぜそれが起こっているのですか?
PHPには、テキストのエンコードを正しくかつ明確に検出する方法はありますか?

役に立ちましたか?

解決

それが私が起こると予想されることです。

検出アルゴリズムは、おそらくあなたが指定したエンコーディングを順番に試し続けています mb_detect_order そして、バイテストリームが有効になる最初のものを返します。

よりインテリジェントなものには統計的方法が必要です(機械学習が一般的に使用されると思います)。

編集:例を参照してください この記事 よりインテリジェントな方法。

その重要性のため、自動charSet検出は、MozillaやInternet Explorerなどの主要なインターネットアプリケーションですでに実装されています。それらは非常に正確で高速ですが、実装はケースバイケースのベースで多くのドメイン固有の知識を適用します。それらの方法とは対照的に、すべてのcharSetに均一に適用できる単純なアルゴリズムを目指し、アルゴリズムは十分に確立された標準的な機械学習技術に基づいています。また、言語とcharset検出の関係を研究し、バイトベースのアルゴリズムと文字ベースのアルゴリズムを比較しました。ナイーブベイズ(NB)とサポートベクターマシン(SVM)を使用しました。

他のヒント

あまり。多くの場合、異なるエンコーディングには大きな領域があり、テストしている文字列がそのオーバーラップ内に存在する場合、両方のエンコードが許容されます。

たとえば、UTF-8およびISO-8859-1は文字AZで同じです。文字列「hello」には、両方のエンコーディングに同一のバイトシーケンスがあります。

これがまさにある理由です mb_detect_order() そもそも機能します。これらの衝突が起こったときに起こりたいことを言うことができるからです。 UTF-8またはISO-8859-1に「こんにちは」をご希望ですか?

留意してください mb_detect_encoding() データのエンコードが何であるかはわかりません。文字列が表示される場合がありますが、関数自体にはバイトのストリームのみが表示されます。それを進めると、エンコードが何であるかを推測する必要があります - たとえば、バイトが0-127の範囲にある場合、UTF-8はASCIIバイトとペア以上にのみ存在する128+バイトがある場合になります。など。

ご想像のとおり、その文脈を考えると、エンコーディングを確実に検出することは非常に困難です。

好き rihk 言った、これが何だ mb_detect_order() 機能は次のとおりです - 基本的に、データが何であるかを推測するのが最善です。 UTF-8ファイルを頻繁に使用していますか?それから、あなたのものはUTF-16であってもそうではない可能性があります mb_detect_encoding() それを推測することができます。

あなたもチェックアウトしたいかもしれません Artefacto's リンク より詳細なビューのために。

例の場合: インターネットエクスプローラ 何も指定されていない場合(@link、セクション:「ウェブサイトの言語を自動的に検出するために」)、いくつかの興味深いエンコード推測を使用します。あなたがグーグルでグーグルであるならば、あなたはおそらくそれにいくつかの面白いものを見つけることができます。統計的方法でさえ恐ろしく裏目に出ることができるのは、一般的なエンコーディングの推測に問題がある理由を順調に見せます。

MB_DETECT_ENCODING MB_DETECT_ORDER()の最初のチャーセットエントリを調べ、その文字がCHARSETの有効な文字セットに該当するかどうかにかかわらず、入力$ HTMLマッチング文字を文字でループします。すべての文字が一致する場合、それは真実に戻ります。キャラクターが失敗した場合、MB_DETECT_ORDER()の次のチャーセットに移動し、再び試みます。

charsetsのウィキペディアリスト 各チャーセットを構成するキャラクターを見るのに良い場所です。

これらの炭化値が重複するため(char x8fa1efは「utf-8」と「euc-jp」の両方に存在するため)これは、各文字セットでまったく異なる文字であるにもかかわらず一致と見なされます。したがって、文字値のいずれかが1つのチャーセットに存在しない限り、別の文字には存在しない限り、MB_DETECT_ENCODINGは、どれが無効であるかを識別できません。有効なアレイリストから最初のcharsetを返します。

私が知っている限り、憲章を識別する確実な方法はありません。 PHPの「最良の推測」方法は、遭遇する可能性がある充電を合理的に考えていれば、各憲章のギャップ(無効な文字)に基づいてリストを注文する場合に役立ちます。最良の解決策は、チャーセットを「知る」ことです。別のページからHTMLを削っている場合は、そのページのヘッダーにcharset識別子を探してください。

本当に賢くなりたい場合は、おそらくトリグラムやn-gramsなどを使用して、HTMLが書かれている言語を識別して識別することができます。 この記事 PHP/IRで。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top