34572


**文字化けしている文字列かどうか条件分岐する方法はありますか？**  
・本来であれば文字エンコーディングを調整すべきだと思うのですが、調整できないという前提で…  
・日本語が含まれているかどうか判定すれば良い？  
・どうやって？？？

**文字化け例**  
・ã»ã¯ã¬ã¸ããã«ã¼ã

* * *

・ちなみに、この文字化けはどういう原因かこれだけから推測可能ですか？

* * *

**2017/5/9追記**

・別の所で取得したデータが一箇所に集められていて、どういう状況で取得したか分からない  
・その中で一部の文字だけが「文字化け」しているかもしれない  
・この時、「文字化け」している文字が混ざっているかどうか判定する方法はあるでしょうか？

[code]

    $str = 'ã»ã¯ã¬ã¸ããã«ã¼ã';
    
    $encAry = [
      'UTF-8',
      'UTF-7',
      'ASCII',
      'EUC-JP',
      'eucJP-win',
      'SJIS',
      'SJIS-win',
      'JIS',
      'ISO-2022-JP',
      'Unicode',
    ];
    
    foreach ($encAry as $val) {
      var_dump(mb_check_encoding($str, $val));
    }
    
    // bool(true)
    // bool(false)
    // bool(false)
    // bool(true)
    // bool(true)
    // bool(true)
    // bool(true)
    // bool(false)
    // bool(false)
    // bool(true)
    
[/code]


CC BY-SA 3.0
2017-04-26T07:42:06.753
34287
2017-05-09T05:38:50.663
2017-05-09T02:59:20.030
7886
7886
question
php
対象文字列が文字化けしているかどうか条件分岐。日本語が含まれているかどうかの判定？


`mb_check_encoding` もしくは `mb_detect_encoding`
で文字列のエンコードを検出し、期待しているエンコードかどうかチェックするのはどうでしょう。


CC BY-SA 3.0
2017-04-26T09:57:00.997
34292
2017-04-26T09:57:00.997
5008
34287
answer


  * **_日本語が含まれているかどうか判定すれば良い？_**
  * **_この時、「文字化け」している文字が混ざっているかどうか判定する方法はあるでしょうか？_**

結論から言うと、アルゴリズミックに確実に判定するのは不可能でしょう。一番大きな理由としては、下記の推測の過程に挙げましたが「一部の情報が欠落しているから」です。

* * *

### 文字化け例

  * ã»ã¯ã¬ã¸ããã«ã¼ã

  * **_ちなみに、この文字化けはどういう原因かこれだけから推測可能ですか？_**

経験と勘で推測する(guess)のであれば、  
・元文字列は「・クレジットカード」  
・エンコーディングはUTF-8  
・文字化けの原因は、UTF-8のバイト列をISO-8859-1として解釈し、さらに一部の制御コードが欠落した  
と言うことになります。

ざっくりと、推測の過程を示しておきます。

  1. 「文字化け」の文字列をISO-8859-1(Latin1)エンコーディングでバイト列に変換してみる

日本語の情報が文字化けするときの典型例であるのと、その際によく現れる文字が含まれているためです。

⇒E3 BB E3 AF E3 AC E3 B8 E3 E3 E3 AB E3 BC E3

[文字コード表ISO-8859-1](https://charset.uic.jp/show/iso-8859-1/)

  2. E3が大量に現れることからUTF-8、おそらく日本語であると推定される

UTF-8で日本語文字を表現した場合、日本語でよく使う漢字やひらがなカタカナなどはみな、E3 xx
xxで表されるコード領域にあります。(xxは80...BF)

[UTF-8コード表(1)](http://seiai.ed.jp/sys/text/java/utf8table.html)

  3. E3 xx xxの形式になっていない部分はISO-8859-1で未定義の制御コード領域となっている80...9Fの部分がコピペ編集等の過程で欠落したものと考える

制御コードを含む文字列をブラウザやターミナルに表示させた後、コピペしてエディターやWebの入力フォームに貼り付けると、制御コードの部分が失われます。

  4. xxの部分は上記の通り80...9Fと仮定し、欠落した部分を推定する
[code]     E3 BB ⇒ E3 xx BB 〻ほセ・ㄻㅻㆻㇻ㈻㉻㊻㋻㌻㍻㎻㏻㐻㑻㒻㓻㔻㕻㖻㗻㘻㙻㚻㛻㜻㝻㞻㟻

    E3 AF ⇒ E3 xx AF  〯はクワㄯㅯㆯ㇯㈯㉯㊯㋯㌯㍯㎯㏯㐯㑯㒯㓯㔯㕯㖯㗯㘯㙯㚯㛯㜯㝯㞯㟯
    E3 AC ⇒ E3 xx AC  〬ぬガレㄬㅬㆬ㇬㈬㉬㊬㋬㌬㍬㎬㏬㐬㑬㒬㓬㔬㕬㖬㗬㘬㙬㚬㛬㜬㝬㞬㟬
    E3 B8 ⇒ E3 xx B8 〸へジヸㄸㅸㆸㇸ㈸㉸㊸㋸㌸㍸㎸㏸㐸㑸㒸㓸㔸㕸㖸㗸㘸㙸㚸㛸㜸㝸㞸㟸
    E3    ⇒ E3 xx xx (候補が多すぎるので後回し)
    E3    ⇒ E3 xx xx (候補が多すぎるので後回し)
    E3 AB ⇒ E3 xx AB  〫にカルㄫㅫㆫ㇫㈫㉫㊫㋫㌫㍫㎫㏫㐫㑫㒫㓫㔫㕫㖫㗫㘫㙫㚫㛫㜫㝫㞫㟫
    E3 BC ⇒ E3 xx BC 〼ぼゼーㄼㅼㆼㇼ㈼㉼㊼㋼㌼㍼㎼㏼㐼㑼㒼㓼㔼㕼㖼㗼㘼㙼㚼㛼㜼㝼㞼㟼
    E3    ⇒ E3 xx xx (候補が多すぎるので後回し)
    
[/code]

(合成用文字等が含まれるので、一部のブラウザでは正しく表示できないかもしれません。悪しからず。)

  5. 上記の候補から日本語では滅多に使わない文字や記号を省いて、意味の通りそうな組み合わせを考える
[code]     ・クレジ□□カー□

    
[/code]

  6. 当然内容は「・クレジットカード」だと推定されるので、「ッ」「ト」「ド」の文字コードが上記のE3 xx xx (xxは80...9F)にマッチすることを調べます。
[code]     ッ: E3 83 83

    ト: E3 83 88
    ド: E3 83 89
    
[/code]

どの文字も80...9Fのバイトが欠落すればE3だけになってしまう、と言う条件を満たしますので、上記の推定が補強されたと言うことになります。

* * *

せめて情報が欠落してしまう前のバイト列を取得できれば、比較的簡単な方法(mb_系の関数)でエンコーディングを推定することもできたでしょうが、ご質問文のようにWebフォームに貼り付けられて元情報の一部が完全に欠落してしまうと、もう機械的な推定はほぼ不可能だと思います。(上記の推測にしても、もしかしたら別に日本語あるいは他の言語として自然な文字列があるかもしれません。)

私的にはどういう状況でどんな方法でそのデータを取得したのかがわからなければ、もう経験と勘に頼る(それも確実ではない)しかないのではないか、と言うのが結論です。


CC BY-SA 3.0
2017-05-09T05:22:58.780
34572
2017-05-09T05:38:50.663
2017-05-09T05:38:50.663
13972
13972
34287
answer