Dize olmayan utf8 karakterleri kaldırma

12 Cevap php

Im düzgün gösterilmiyor dize, olmayan utf8 karakterleri kaldırılması ile ilgili bir sorun yaşıyorsanız. Karakterler bu 0x97 gibi 0x61 0x6C 0x6F (onaltılık gösterimi)

Bunları kaldırmak için en iyi yolu nedir? Düzenli ifade veya başka bir şey?

12 Cevap

Regex yaklaşımı kullanarak:

$regex = <<<'END'
/
  (
    (?: [\x00-\x7F]                 # single-byte sequences   0xxxxxxx
    |   [\xC0-\xDF][\x80-\xBF]      # double-byte sequences   110xxxxx 10xxxxxx
    |   [\xE0-\xEF][\x80-\xBF]{2}   # triple-byte sequences   1110xxxx 10xxxxxx * 2
    |   [\xF0-\xF7][\x80-\xBF]{3}   # quadruple-byte sequence 11110xxx 10xxxxxx * 3 
    ){1,100}                        # ...one or more times
  )
| .                                 # anything else
/x
END;
preg_replace($regex, '$1', $text);

Bu UTF-8 dizileri için arar, ve grup 1 içine bu yakalar. Ayrıca UTF-8 dizisinin bir parçası olarak tespit edilemeyen tek bayt maçlar, ama o yakalamak değil. Yedek grup 1 içine yakalandı odur. Bu etkili tüm geçersiz bayt kaldırır.

Bu UTF-8 karakter olarak geçersiz bayt kodlama, dize onarmak mümkündür. Hataları rasgele Ama eğer, bu bazı garip semboller bırakabilir.

$regex = <<<'END'
/
  (
    (?: [\x00-\x7F]               # single-byte sequences   0xxxxxxx
    |   [\xC0-\xDF][\x80-\xBF]    # double-byte sequences   110xxxxx 10xxxxxx
    |   [\xE0-\xEF][\x80-\xBF]{2} # triple-byte sequences   1110xxxx 10xxxxxx * 2
    |   [\xF0-\xF7][\x80-\xBF]{3} # quadruple-byte sequence 11110xxx 10xxxxxx * 3 
    ){1,100}                      # ...one or more times
  )
| ( [\x80-\xBF] )                 # invalid byte in range 10000000 - 10111111
| ( [\xC0-\xFF] )                 # invalid byte in range 11000000 - 11111111
/x
END;
function utf8replacer($captures) {
  if ($captures[1] != "") {
    // Valid byte sequence. Return unmodified.
    return $captures[1];
  }
  elseif ($captures[2] != "") {
    // Invalid byte of the form 10xxxxxx.
    // Encode as 11000010 10xxxxxx.
    return "\xC2".$captures[2];
  }
  else {
    // Invalid byte of the form 11xxxxxx.
    // Encode as 11000011 10xxxxxx.
    return "\xC3".chr(ord($captures[3])-64);
  }
}
preg_replace_callback($regex, "utf8replacer", $text);

EDIT:

  • !empty(x) boş olmayan değerler ("0" boş kabul edilir) maç olacak.
  • x != "" "0" gibi boş olmayan değerleri, maç olacaktır.
  • x !== "" "" dışında bir şey maç olacak.

x != "" Bu durumda kullanmanız için en iyi olanı gibi görünüyor.

Ben de maç biraz hızlandırdı. Bunun yerine ayrı ayrı karakteri eşleşen, geçerli UTF-8 karakter dizileri ile eşleştirilir.

Aşağıda iyi çalıştı.

<?php

$string = "Remove these characters: äó";
$string = preg_replace('/[^(\x20-\x7F)]*/','', $string);

?>

See source here

Eğer zaten UTF8 dize utf8_encode () uygularsanız o bozuk bir UTF8 çıktı dönecektir.

Tüm bu sorunları gideren bir işlev yaptı. Bu Kodlama :: toUTF8 () denir.

Sen dizeleri kodlama ne olduğunu bilmek gerekmez. Bu Latin1 (iso 8859-1), Windows 1252 veya UTF8 veya dize bunların bir karışımı olabilir olabilir. Kodlama :: toUTF8 () UTF8 için her şeyi dönüştürmek olacaktır.

Bir hizmet, aynı dizede bu kodlamaları karıştırma, bana bütün berbat bir veri beslemesi veriyordu çünkü ben yaptım.

Kullanımı:

require_once('Encoding.php'); 
use \ForceUTF8\Encoding;  // It's namespaced now.

$utf8_string = Encoding::toUTF8($mixed_string);

$latin1_string = Encoding::toLatin1($mixed_string);

Ben başka bir işlevi, kodlama :: fixUTF8 () dahil ettik, wich UTF8 birden çok kez içine kodlanmış olmanın bozuk ürünü görünüyor her UTF8 dizesi çözecektir.

Kullanımı:

require_once('Encoding.php'); 
use \ForceUTF8\Encoding;  // It's namespaced now.

$utf8_string = Encoding::fixUTF8($garbled_utf8_string);

Örnekler:

echo Encoding::fixUTF8("Fédération Camerounaise de Football");
echo Encoding::fixUTF8("Fédération Camerounaise de Football");
echo Encoding::fixUTF8("FÃÂédÃÂération Camerounaise de Football");
echo Encoding::fixUTF8("Fédération Camerounaise de Football");

çıktısı:

Fédération Camerounaise de Football
Fédération Camerounaise de Football
Fédération Camerounaise de Football
Fédération Camerounaise de Football

İndir:

https://github.com/neitanod/forceutf8

$text = iconv("UTF-8", "UTF-8//IGNORE", $text);

Bu ben kullanıyorum budur. Oldukça iyi iş gibi görünüyor. http://planetozh.com/blog/2005/01/remove-invalid-characters-in-utf-8/ alınan

Sen mbstring'i kullanabilirsiniz:

$text = mb_convert_encoding($text, 'UTF-8', 'UTF-8');

... Geçersiz karakterler kaldıracaktır.

Bkz: Replacing invalid UTF-8 characters by question marks, mbstring.substitute_character seems ignored

UConverter PHP 5.5 beri kullanılabilmektedir. Eğer intl uzantısını kullanan ve mbstring'i kullanmak istemiyorsanız UConverter daha iyi bir seçimdir.

function replace_invalid_byte_sequence($str)
{
    return UConverter::transcode($str, 'UTF-8', 'UTF-8');
}

function replace_invalid_byte_sequence2($str)
{
    return (new UConverter('UTF-8', 'UTF-8'))->convert($str);
}

htmlspecialchars'ın PHP 5.4 beri geçersiz bir bayt dizisini kaldırmak için kullanılabilir. Htmlspecialchars büyük bayt boyutu ve doğruluğunu işleme için preg_match'in daha iyidir. Düzenli ifade kullanarak yanlış uygulama bir çok görülebilir.

function replace_invalid_byte_sequence3($str)
{
    return htmlspecialchars_decode(htmlspecialchars($str, ENT_SUBSTITUTE, 'UTF-8'));
}

Yani kurallar ilk UTF-8 octlet bir işaretleyici olarak ayarlanmış yüksek parça var, ve daha sonra 1-4 bit kaç ek octlets göstermek için vardır; sonra ek octlets her 10 set yüksek iki bit olmalıdır.

Pseudo-python olacaktır:

newstring = ''
cont = 0
for each ch in string:
  if cont:
    if (ch >> 6) != 2: # high 2 bits are 10
      # do whatever, e.g. skip it, or skip whole point, or?
    else:
      # acceptable continuation of multi-octlet char
      newstring += ch
    cont -= 1
  else:
    if (ch >> 7): # high bit set?
      c = (ch << 1) # strip the high bit marker
      while (c & 1): # while the high bit indicates another octlet
        c <<= 1
        cont += 1
        if cont > 4:
           # more than 4 octels not allowed; cope with error
      if !cont:
        # illegal, do something sensible
      newstring += ch # or whatever
if cont:
  # last utf-8 was not terminated, cope

Aynı mantık php çevrilebilir olmalıdır. Ancak, onun net değil bozuk bir karakter olsun bir kez yapılması gereken sıyırma ne türüdür.

Nasıl iconv hakkında:

http://php.net/manual/en/function.iconv.php

Kendisi ama onun her zaman komut satırında benim için iyi performans PHP içine kullanmadım. Bunu geçersiz karakterler yerine alabilirsiniz.

Burada listelenen çözümleri yüzden burada bölümü "Karakter doğrulaması" in cevabı buldum benim için işe yaramadı:

http://webcollab.sourceforge.net/unicode.html

Unicode temel dil düzlemin dışında tüm Unicode karakterleri kaldırmak için:

$ Str = preg_replace ("/ [^ \ x00-\ xFFFF] /", "", $ str);

Bu her zaman ne olursa olsun kodlama, çalışır benim işlevi:

FUNCTION RemoveBS($Str) {  
  $StrArr = STR_SPLIT($Str); $NewStr = '';
  FOREACH ($StrArr AS $Char) {    
    $CharNo = ORD($Char);
    IF ($CharNo == 163) { $NewStr .= $Char; CONTINUE; } // keep £ 
    IF ($CharNo > 31 && $CharNo < 127) {
      $NewStr .= $Char;    
    }
  }  
  RETURN $NewStr;
}

Nasıl çalışır:

echo RemoveBS('Hello õhowå åare youÆ?'); // Hello how are you?

Biraz soruya farklı, ama ne yapıyorum HtmlEncode (dize) kullanmak için

Burada sahte kod

var encoded = HtmlEncode(string);
encoded = Regex.Replace(encoded, "&#\d+?;", "");
var result = HtmlDecode(encoded);

giriş ve çıkış

"Headlight\x007E Bracket, &#123; Cafe Racer<> Style, Stainless Steel 中文呢?"
"Headlight~ Bracket, &#123; Cafe Racer<> Style, Stainless Steel 中文呢?"

Ben mükemmel değil, ama benim için bu işi yapar biliyorum.