PHPでファイルがUTF-8符号化されているかどうかを検出する関数

1926 ワード

// 
//        utf8  
// 
//    :
//   1 -  BOM    
//   2 -  utf8   
//   3 -     utf8   
//   4 -      utf8   
// 
function utf8_check($text)
{
  $utf8_bom = chr(0xEF).chr(0xBB).chr(0xBF);
  
  // BOM   
  if (strstr($text, $utf8_bom) === 0)
    return 1;
  
  $text_len = strlen($text);
  
  // UTF-8           。        UTF-8  ,                 0;
  //       ,            ,         1            ,       10  。
  // UTF-8     6   。
  //
  //   :
  // < 0x80 1   0xxxxxxx
  // < 0xE0 2   110xxxxx 10xxxxxx
  // < 0xF0 3   1110xxxx 10xxxxxx 10xxxxxx
  // < 0xF8 4   11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
  // < 0xFC 5   111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
  // < 0xFE 6   1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
  
  $bad   = 0; //    utf8      
  $good  = 0; //   utf8      
  
  $need_check = 0; //       utf8   ,          
  $have_check = 0; //            
  
  for ($i = 0; $i < $text_len; $i ++) {
    $c = ord($text[$i]);

    if ($need_check > 0) {
      $c = ord($text[$i]);
      $c = ($c >> 6) << 6;
      
      $have_check ++;
      
      // 10xxxxxx ~ 10111111
      if ($c != 0x80) {
        $i -= $have_check;
        $need_check = 0;
        $have_check = 0;
        $bad ++;
      }
      else if ($need_check == $have_check) {
        $need_check = 0;
        $have_check = 0;
        $good ++;
      }
      
      continue;
    }
    
    if ($c < 0x80)      // 0xxxxxxx
      $good ++;
    else if ($c < 0xE0) // 110xxxxx
      $need_check = 1;
    else if ($c < 0xF0) // 1110xxxx
      $need_check = 2;
    else if ($c < 0xF8) // 11110xxx
      $need_check = 3;
    else if ($c < 0xFC) // 111110xx
      $need_check = 4;
    else if ($c < 0xFE) // 1111110x
      $need_check = 5;
    else
      $bad ++;
  }
  
  if ($bad == 0)
    return 2;
  else if ($good > $bad)
    return 3;
  else
    return 4;
}