PHP geçerli utf-8 sağlanması

6 Cevap php

Ben çeşitli kaynaklardan metin işlemek için PHP kullanıyorum. Ben UTF-8, ISO-8859-1, ya da belki WINDOWS-1252 dışında başka bir şey olacak beklemiyoruz. Bunlardan bir tanesi başka bir şey varsa, ben sadece karakterler kaybolmuş olsa bile, metin geçerli bir UTF-8 dizesi dönüştü alır emin olmak gerekir. Iconv / / DAMGAÇEVİRİSİ seçeneği bu çözdü mü? Örneğin, bu kod bir dize UTF-8 kodlu belge (veya veritabanı) eklemek için güvenli olduğundan emin olmak istiyorsunuz?

function make_safe_for_utf8_use($string) {

    $encoding = mb_detect_encoding($string, "UTF-8,ISO-8859-1,WINDOWS-1252");

    if ($encoding != 'UTF-8') {
        return iconv($encoding, 'UTF-8//TRANSLIT', $string);
    } else {
        return $string;
    }
}

Thanks very much, Brian

6 Cevap

UTF-8 Unicode karakter saklayabilirsiniz. Seninkodlamamod ISO-8859-1 veya Windows 1252 dahil olmak üzere bütün başka bir şey ise, UTF-8 içinde her karakter saklayabilirsiniz. Yani UTF-8 için başka bir kodlama bir dize dönüştürmek olduğunda herhangi bir karakter kaybetme konusunda endişelenmenize gerek yok.

Ayrıca, ISO-8859-1 ve Windows-1252 hem de herhangi bir bayt geçerlidir tek baytlık kodlamaları vardır. Bu onları ayırt etmek teknik olarak mümkün değildir. Farklı çözmek sadece bayt aralığı 0x80-0x9F olduğu gibi, non-UTF-8 dizileri için varsayılan maç olarak Windows 1252 seçti. ISO-8859-1 hemen hemen hiç kullanılmamış olan görünmez kontrol karakterleridir ise akıllı tırnaklar ve Windows 1252 yılında Euro gibi çeşitli karakterler bu decode,. Web tarayıcıları bazen ISO-8859-1 kullanılarak, ama genellikle gerçekten Windows 1252 kullanarak olacaktır söyleyebiliriz.

Bu kod UTF-8 kodlu belgeye eklemek için bir dize güvenli olduğundan emin olmak istiyorum

Kesinlikle bu amaçla TRUE isteğe bağlı 'sıkı' parametresini ayarlamak isterim. Ama bu aslında tüm geçersiz UTF-8 dizileri kapsar emin değilim. Fonksiyonu açıkça UTF-8 geçerliliği için bir bayt dizisi kontrol etmek iddiasında değildir. Hala sıkı modunda olabilir eğer ben bilmiyorum ama, mb_detect_encoding hatalı önce UTF-8 tahmin ediyorum bilinen olgu olmuştur.

Eğer emin olmak istiyorsanız, W3-recommended regex kullanarak kendiniz yapın:

if (preg_match('%^(?:
      [\x09\x0A\x0D\x20-\x7E]            # ASCII
    | [\xC2-\xDF][\x80-\xBF]             # non-overlong 2-byte
    | \xE0[\xA0-\xBF][\x80-\xBF]         # excluding overlongs
    | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}  # straight 3-byte
    | \xED[\x80-\x9F][\x80-\xBF]         # excluding surrogates
    | \xF0[\x90-\xBF][\x80-\xBF]{2}      # planes 1-3
    | [\xF1-\xF3][\x80-\xBF]{3}          # planes 4-15
    | \xF4[\x80-\x8F][\x80-\xBF]{2}      # plane 16
)*$%xs', $string))
    return $string;
else
    return iconv('CP1252', 'UTF-8', $string);

mbstring kütüphanesi ile, mb_check_encoding() var.

Kullanım örneği:

mb_check_encoding($string, 'UTF-8');

Performans hususlar, bu kabul edilen yanıt sağlanan düzenli ifade daha hızlı olduğu zaman.

(20.000 tekrarlamalar için) benim yapılandırma gösterileri hızlı bir test:

  • regex: ~310ms
  • mb_check_encoding: ~90ms

Sadece bir not: Bunun yerine sık sık tavsiye (oldukça karmaşık) kullanarak regular expression by W3C, basitçe kullanabilirsiniz 'u' UTF-8 geçerliliği için bir dize test değiştirici:

<?php
  if (preg_match("//u", $string)) {
      // $string is valid UTF-8
  }

Karakter setlerinin hakkında bir kılavuz için http://www.phpwact.org/php/i18n/charsets bakabilirsiniz. Bu sayfa özellikle utf8 için bir sayfaya bağlantı sağlar.

cevap "iconv İdempotent olduğunu"

iconv olduğunu ne - iconv İdempotent değil

a big difference between utf8_encode() & iconv() is that iconv may raise errors like this "Detected an incomplete multibyte character in input string" even with

iconv ('ISO-8859-1', 'UTF-8'. '/ / Yoksay', $ str)

Yukarıdaki kodu:

$ Kodlama = mb_detect_encoding ($ string, "UTF-8, ISO-8859-1, WINDOWS-1252");

Eğer mb_detect_encoding bile geçersiz utf-8 dizeleri için DTM-8 cevap verebilir bilmek zorunda (kötü kurdu utf8)

Emin değil bu aynı şeyi başarmak istiyorum, ama sadece algılama endişesi olmadan tüm metin üzerinde utf8_encode() kullanmak olurdu? Metin zaten UTF-8 ise, ona zarar vermez. O değil Ve eğer, dönüştürülür. Zaten bu yaptığını düşündüm ettiyseniz, bu sizin için işe yaramaz bir nedeni var mı?