2011-12-13 9 views
21

Sembra che MySQL does not support caratteri con più di 3 byte nel set di caratteri UTF-8 predefinito.Come sostituire/rimuovere 4 (+) - caratteri di byte da una stringa UTF-8 in PHP?

Quindi, in PHP, come posso sbarazzarmi di tutti e 4 (e più) i caratteri in una stringa e sostituirli con qualcosa di simile ad un altro personaggio?

+1

Sei sicuro che i dati con cui stai operando conterranno mai caratteri che non rientrano nel utf8 a 3 byte di mysql? – newtover

+1

Sei sicuro che anche * siano * caratteri simili? 3 byte ti danno l'intero piano multilingue di base; se hai bisogno di caratteri molto più rari al di là di questo, prendi in considerazione un'altra codifica Unicode (ad es. utf-16). – Piskvor

+1

Il problema è che voglio evitare gli altri, perché MySQL tronca i testi a quel punto se qualcuno inserisce uno di quei caratteri speciali lì dentro. – Franz

risposta

2

Ecco un esempio:

<?php 

mb_internal_encoding("UTF-8"); 

//utf8 string, 13 bytes, 9 utf8 chars, 7 ASCII, 1 in latin1, 1 outside the BMP 
$str = "qué \xF0\x9D\x92\xB3 tal"; 
$array = mbStringToArray($str); 
print "str: [$str] strlen:" . strlen($str) . " chars:" . count($array) . "\n"; 
$str1 = ""; 
foreach($array as $c) { 
    // print "$c : " . strlen($c) ."\n"; 
    $str1 .= strlen($c)<=3? $c : '?'; 
} 
print "[$str1]\n"; 


function mbStringToArray ($str) { 
    if (empty($str)) return false; 
    $len = mb_strlen($str); 
    $array = array(); 
    for ($i = 0; $i < $len; $i++) { 
     $array[] = mb_substr($str, $i, 1); 
    } 
    return $array; 
} 

Oppure, un po 'più compatto ed efficiente:

<?php /// 

mb_internal_encoding("UTF-8"); 

//utf8 string, 13 bytes, 9 utf8 chars, 7 ASCII, 1 in latin1, 1 outside the BMP 
$str = "qué \xF0\x9D\x92\xB3 tal"; 
$str1 = trimOutsideBMP($str); 
print "original: [$str]\n"; 
print "trimmed: [$str1]\n"; 


// Replaces non-BMP characters in the UTF-8 string by a '?' character 
// Assumes UTF-8 default encoding (if not sure, call first mb_internal_encoding("UTF-8");) 
function trimOutsideBMP($str) { 
    if (empty($str)) return $str; 
    $len = mb_strlen($str); 
    $str1 = ''; 
    for ($i = 0; $i < $len; $i++) { 
     $c = mb_substr($str, $i, 1); 
     $str1 .= strlen($c) <= 3 ? $c : '?'; 
    } 
    return $str1; 
} 
+0

Oh, dovrei aver detto che ho bisogno di una soluzione che non richiede l'estensione 'mbstring'? – Franz

+0

Mmm è brutto. Vedi ad esempio qui per l'ispirazione: http://noteslog.com/post/full-utf-8-support-in-wordpress/ – leonbloy

1

sono imbattuto in questa domanda quando si cerca di risolvere il mio problema (Facebook sputa fuori alcune emoticons come 4 -Dopo i caratteri, Amazon Mechanical Turk non accetta caratteri a 4 byte).

Ho finito per usare questo, non richiede l'estensione mbstring:

function remove_4_byte($string) { 
    $char_array = preg_split('/(?<!^)(?!$)/u', $string); 
    for($x=0;$x<sizeof($char_array);$x++) { 
     if(strlen($char_array[$x])>3) { 
      $char_array[$x] = ""; 
     } 
    } 
    return implode($char_array, ""); 
} 
+0

Per qualche motivo non ho potuto far funzionare gli altri, questo fa il trucco. – Mahn

9

Dal 4 byte UTF-8 sequenze iniziano sempre con il byte 0xF0-0xF7, il seguente dovrebbe funzionare:

$str = preg_replace('/[\xF0-\xF7].../s', '', $str); 

in alternativa, è possibile utilizzare preg_replace in UTF-8 modalità, ma questo sarà probabilmente più lenta:

$str = preg_replace('/[\x{10000}-\x{10FFFF}]/u', '', $str); 

Questo funziona perché le sequenze UTF-8 a 4 byte vengono utilizzate per i punti di codice nei piani Unicode supplementari a partire da 0x10000.

1

Sotto cambiamento funzione 3 e 4 personaggi byte da utf8 stringa da '#':

function remove3and4bytesCharFromUtf8Str($str) { 
     return preg_replace('/([\xF0-\xF7]...)|([\xE0-\xEF]..)/s', '#', $str); 
    } 
0

Ecco la mia implementazione di filtrare i caratteri a 4 byte

0.123.
$string = preg_replace_callback(
    '/./u', 
    function (array $match) { 
     return strlen($match[0]) >= 4 ? null : $match[0]; 
    }, 
    $string 
); 

si potrebbe modificarlo e sostituire null (che rimuove il char) con qualche stringa sostituto. È inoltre possibile sostituire >= 4 con un altro controllo a lunghezza di byte.

Problemi correlati