Bir dize UTF-8 olarak kodlanmış olup olmadığını görmek için kontrol edin

3 Cevap php
function seems_utf8($str) {
 $length = strlen($str);
 for ($i=0; $i < $length; $i++) {
  $c = ord($str[$i]);
  if ($c < 0x80) $n = 0; # 0bbbbbbb
  elseif (($c & 0xE0) == 0xC0) $n=1; # 110bbbbb
  elseif (($c & 0xF0) == 0xE0) $n=2; # 1110bbbb
  elseif (($c & 0xF8) == 0xF0) $n=3; # 11110bbb
  elseif (($c & 0xFC) == 0xF8) $n=4; # 111110bb
  elseif (($c & 0xFE) == 0xFC) $n=5; # 1111110b
  else return false; # Does not match any model
  for ($j=0; $j<$n; $j++) { # n bytes matching 10bbbbbb follow ?
   if ((++$i == $length) || ((ord($str[$i]) & 0xC0) != 0x80))
    return false;
  }
 }
 return true;
}

Ben bu konuda çok Wordpress bu kod bilmiyorum var, ama ben tam olarak bu işlevi happing bilmek istiyorum.

Herhangi bir biliyorsanız bana yardım edin?

Ben yukarıdaki kodu hakkında net bir fikir gerekir. Satır satır açıklama daha yararlı olacaktır eğer.

3 Cevap

Byte dizisi Eğer Wikipedia article görebilirsiniz desen uygunsa bu algoritma, temelde kontrol ediyor.

for döngü tüm bayt geçmesi için $str. ord geçerli bayt ondalık sayı alır. Bu sayı daha sonra bazı özellikleri için test edilir.

Sayısı az 128 (0x80), tek bir bayt karakter eğer. Eşit veya 128 daha büyük ise, multi-byte karakter uzunluğu kontrol edilir. Bu bir çoklu-bayt karakter dizisinin ilk karakteri ile yapılır yapabilirsiniz. , Ilk bayt 110xxxxx, bir iki bayt karakter ile başlar 1110xxxx, bu üç bayt karakter, vb bulunuyor

Ben en esrarlı parçalar ($c & 0xE0) == 0xC0 gibi ifadeler olduğunu düşünüyorum. Bu ikili formatta sayı bazı özel desen olup olmadığını kontrol etmektir. Ben aynı örnek üzerinde nasıl çalıştığını anlatmaya çalışacağım.

O model test eden bütün sayılar, a eşit ya da daha büyük olan 0x80 için, ilk baytı her zaman 1 olduğu, bu yüzden, en azından model 1xxxxxxxx ile sınırlandırılmıştır. Biz o 11100000 (0xE0) ile biraz-bilge VE karşılaştırma yaparsanız, biz bu sonucu alırsınız:

  1xxxxxxx
& 11100000
= 1xx00000

Yani pozisyon 5 ve 6'da bit bizim mevcut sayısı ne bağlıdır (0 dizini başladı, sağdan okuyun). 11000000 eşit, 5. bit 0 olmalı ve 6. bit olması gerektiğini var 1:

  1xxxxxxx
& 11100000
≟ 11000000
   ↓↓
→ 110xxxxx

Bu sayımızın diğer bit keyfi olabilir anlamına gelir: 110xxxxx. Ve bu Wikipedia makalesinde desen bir iki bayt karakter kelimenin ilk byte için tahmin tam olarak budur.

Ve iç for döngü bir multi-byte karakter aşağıdaki bayt aklı kontrol etmektir son. Tüm bu 10xxxxxx ile başlamalıdır.

Ben dize (duruma göre) utf-8 olup olmadığını kontrol etmek için iki şekilde kullanabilirsiniz:

mb_internal_encoding('UTF-8'); // always needed before mb_ functions, check note below
if (mb_strlen($string) != strlen($string)) {
 /// not single byte
}

- VEYA -

if (preg_match('!\S!u', $string)) {
 // utf8
}

Nedeniyle MB_ bir işleve parametre olarak kodlama geçen çalışmak ve iç kodlama önce ayarlanmış olması gerekmektedir değildir (5.3-(5.3 üzerinde test değil) sürüm) php hata bana bazı bilinmeyen - mb_internal_encoding için MB_ işlevlerinin herhangi kullanılması.

UTF-8 hakkında biraz biliyorsanız bu oldukça basit bir uygulama var.

function seems_utf8($str) {
 # get length, for utf8 this means bytes and not characters
 $length = strlen($str);  

 # we need to check each byte in the string
 for ($i=0; $i < $length; $i++) {

  # get the byte code 0-255 of the i-th byte
  $c = ord($str[$i]);

  # utf8 characters can take 1-6 bytes, how much
  # exactly is decoded in the first character if 
  # it has a character code >= 128 (highest bit set).
  # For all <= 127 the ASCII is the same as UTF8.
  # The number of bytes per character is stored in 
  # the highest bits of the first byte of the UTF8 
  # character. The bit pattern that must be matched
  # for the different length are shown as comment.
  #
  # So $n will hold the number of additonal characters

  if ($c < 0x80) $n = 0; # 0bbbbbbb
  elseif (($c & 0xE0) == 0xC0) $n=1; # 110bbbbb
  elseif (($c & 0xF0) == 0xE0) $n=2; # 1110bbbb
  elseif (($c & 0xF8) == 0xF0) $n=3; # 11110bbb
  elseif (($c & 0xFC) == 0xF8) $n=4; # 111110bb
  elseif (($c & 0xFE) == 0xFC) $n=5; # 1111110b
  else return false; # Does not match any model

  # the code now checks the following additional bytes
  # First in the if checks that the byte is really inside the
  # string and running over the string end.
  # The second just check that the highest two bits of all 
  # additonal bytes are always 1 and 0 (hexadecimal 0x80)
  # which is a requirement for all additional UTF-8 bytes

  for ($j=0; $j<$n; $j++) { # n bytes matching 10bbbbbb follow ?
   if ((++$i == $length) || ((ord($str[$i]) & 0xC0) != 0x80))
    return false;
  }
 }
 return true;
}

Arada. PHP i gerçekten uzun dizeler ve üretim sistemlerinde kullanmak gerekir bu yüzden bir C işlevi daha yavaş bir faktör 50-100 olduğunu varsayalım.