Tengo el siguiente problema de codificación de caracteres, de alguna manera me las he arreglado para guardar los datos con codificación de caracteres diferente en mi base de datos (UTF8) El código y salidas de debajo de la muestra 2 muestra las cadenas y cómo de salida. 1 de ellos, sería necesario cambiar a UTF8 y el otro ya está.

Cómo hacer/debo ir sobre la comprobación de si debo codificar la cadena o no? por ejemplo,
Necesito cada cadena se imprima correctamente, así que ¿cómo puedo comprobar si ya está utf8 o si necesita ser convertido?

Estoy usando PHP 5.2, mysql tablas myisam:

CREATE TABLE IF NOT EXISTS `entities` (
  ....
  `title` varchar(255) NOT NULL
  ....
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

<?php
$text = $entity['Entity']['title'];
echo 'Original : ', $text."<br />";
echo 'UTF8 Encode : ', utf8_encode($text)."<br />";
echo 'UTF8 Decode : ', utf8_decode($text)."<br />";
echo 'TRANSLIT : ', iconv("ISO-8859-1", "UTF-8//TRANSLIT", $text)."<br />";
echo 'IGNORE TRANSLIT : ', iconv("ISO-8859-1", "UTF-8//IGNORE//TRANSLIT", $text)."<br />";
echo 'IGNORE   : ', iconv("ISO-8859-1", "UTF-8//IGNORE", $text)."<br />";
echo 'Plain    : ', iconv("ISO-8859-1", "UTF-8", $text)."<br />";
?>

Salida 1:

Original : France Télécom
UTF8 Encode : France Télécom
UTF8 Decode : France Tlcom
TRANSLIT : France Télécom
IGNORE TRANSLIT : France Télécom
IGNORE : France Télécom
Plain : France Télécom

Salida 2:###

Original : Cond Nast Publications
UTF8 Encode : Condé Nast Publications
UTF8 Decode : Cond?ast Publications
TRANSLIT : Condé Nast Publications
IGNORE TRANSLIT : Condé Nast Publications
IGNORE : Condé Nast Publications
Plain : Condé Nast Publications

Gracias por tu tiempo en esto. La codificación de caracteres y no me llevo muy bien!

ACTUALIZACIÓN:

echo strlen($string)."|".strlen(utf8_encode($string))."|";
echo (strlen($string)!==strlen(utf8_encode($string))) ? $string : utf8_encode($string);
echo "<br />";
echo strlen($string)."|".strlen(utf8_decode($string))."|";
echo (strlen($string)!==strlen(utf8_decode($string))) ? $string : utf8_decode($string);
echo "<br />";

23|24|Cond Nast Publications
23|21|Cond Nast Publications

16|20|France Télécom
16|14|France Télécom
  • Desde la mirada de ella, la primera cadena ya está en UTF-8, y la segunda es ISO-8859-1. Pero ¿cuál es su pregunta?
  • Yo cada cadena se imprima correctamente, así que ¿cómo puedo comprobar si ya está utf8 o si necesita ser convertido?
  • No estoy seguro, pero echa un vistazo aquí – dev.mysql.com/doc/refman/5.0/en/… – con una buena combinación de funciones de mysql se podía puedes hacer lo que quieras con una sola consulta de actualización.
  • Yo también creo que la fijación de la base de datos una vez es mejor que la re-codificación de la cadena en cada solicitud.
InformationsquelleAutor Lizard | 2010-11-04

6 Comentarios

  1. 28

    Esto puede ser un trabajo para el mb_detect_encoding() función.

    En mi limitada experiencia con ella, no es 100% fiable cuando se utiliza como nombre genérico de «codificación sniffer» – Se comprueba la presencia de ciertos caracteres y valores de byte para hacer una conjetura -, pero en este caso estrecho (se tendrá que distinguir entre UTF-8 y ISO-8859-1) debe trabajo.

    <?php
    $text = $entity['Entity']['title'];
    
    echo 'Original : ', $text."<br />";
    $enc = mb_detect_encoding($text, "UTF-8,ISO-8859-1");
    
    echo 'Detected encoding '.$enc."<br />";
    
    echo 'Fixed result: '.iconv($enc, "UTF-8", $text)."<br />";
    
    ?>

    puede recibir resultados incorrectos para las cadenas que no contienen caracteres especiales, pero que no es un problema.

    • De acuerdo a mi experiencia mb_detect_encoding() no es del todo fiable. Traté de utilizarlo en el pasado pero se vuelve completamente equivocado codificaciones para tantas cadenas.
    • se debe trabajar con un conjunto limitado de posibles codificaciones (UTF-8 debe ser relativamente fáciles de diferenciar de la ISO)… vamos a ver cómo funciona
    • En mi experiencia el orden de encoding_list asuntos. «UTF-8,ISO-8859-1» se dan otros resultados de «ISO-8859-1,UTF-8»
    • Me estaba volviendo loco con esto, gracias tanto @Pekka 웃 para esta solución
    • Para mí, esta era la única solución. Tuvo algunos problemas con la Base de datos SQL Server. Gracias @Pekka웃 para compartir!
  2. 9

    Hice una función que se ocupa de todos estos temas. Su llamado de Codificación::toUTF8().

    <?php
    $text = $entity['Entity']['title'];
    echo 'Original : ', $text."<br />";
    echo 'Encoding::toUTF8 : ', Encoding::toUTF8($text)."<br />";
    ?>

    De salida:

    Original : France Télécom
    Encoding::toUTF8 : France Télécom
    
    Original : Cond Nast Publications
    Encoding::toUTF8 : Condé Nast Publications

    Usted no necesita saber lo que la codificación de las cadenas es tan largo como usted sepa que está en Latin1 (iso 8859-1), Windows-1252 o UTF8. La cadena puede tener una mezcla de ellos.

    De codificación::toUTF8() va a convertir todo en UTF8.

    Lo hice porque un servicio que me estaba dando un feed de datos de todo desordenado, mezcla UTF8 y Latin1 en la misma cadena.

    Uso:

    $utf8_string = Encoding::toUTF8($utf8_or_latin1_or_mixed_string);
    
    $latin1_string = Encoding::toLatin1($utf8_or_latin1_or_mixed_string);

    Descarga:

    http://dl.dropbox.com/u/186012/PHP/forceUTF8.zip

    He incluido otra función de Codificación::fixUFT8(), que va a solucionar todos los UTF8 string que se ve distorsionado.

    Uso:

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

    Ejemplos:

    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");

    de salida será:

    Fédération Camerounaise de Football
    Fédération Camerounaise de Football
    Fédération Camerounaise de Football
    Fédération Camerounaise de Football
    • Buen trabajo, esta clase soluciona todo para mí.
    • Gracias! puede crear un github con esto, con mucho gusto le quiero hacer algunas mejoras.
    • Es en https://github.com/neitanod/forceutf8
  3. 6

    De otra manera, quizás más rápido y menos confiable:

    echo (strlen($str)!==strlen(utf8_decode($str)))
      ? $str                //is multibyte, leave as is
      : utf8_encode($str);  //encode

    Se compara la longitud de la cadena original y el utf8_decoded cadena.
    Una cadena que contiene un carácter multi-byte, tiene un strlen que difiere de la de similar singlebyte codificados en la función strlen.

    Por ejemplo:

    strlen('Télécom') 

    debe devolver 7 en Latin1 y 9 en UTF8

    • Muy bonito! Esto debería funcionar. +1
    • Sí, este parece ser la mejor opción. Todavía se debe copia de seguridad de su base de datos antes de hacer nada 🙂
    • Este método debe ser posible aplicar en la base de datos directamente, también, por la conversión del juego de caracteres en la mosca y la comparación de la longitud de bytes (creo que mySQL tiene una función para eso) … Sólo como una idea para corregir la base de datos más rápidamente
    • Miedo de que esto no funciona… ver la Actualización en mi pregunta
    • Creo que se ha implementado de manera equivocada. Usted necesita a la salida de un utf8_decode a ver si funciona (que está de salida una versión codificada dos veces)
  4. 1

    Hice estos pequeños 2 funciones que funcionan bien con UTF-8 y ISO-8859-1 /detección de conversión…

    function detect_encoding($string)
    {
        //http://w3.org/International/questions/qa-forms-utf-8.html
        if (preg_match('%^(?: [\x09\x0A\x0D\x20-\x7E] | [\xC2-\xDF][\x80-\xBF] | \xE0[\xA0-\xBF][\x80-\xBF] | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} | \xED[\x80-\x9F][\x80-\xBF] | \xF0[\x90-\xBF][\x80-\xBF]{2} | [\xF1-\xF3][\x80-\xBF]{3} | \xF4[\x80-\x8F][\x80-\xBF]{2} )*$%xs', $string))
            return 'UTF-8';
    
        //If you need to distinguish between UTF-8 and ISO-8859-1 encoding, list UTF-8 first in your encoding_list.
        //if you list ISO-8859-1 first, mb_detect_encoding() will always return ISO-8859-1.
        return mb_detect_encoding($string, array('UTF-8', 'ASCII', 'ISO-8859-1', 'JIS', 'EUC-JP', 'SJIS'));
    }
    
    function convert_encoding($string, $to_encoding, $from_encoding = '')
    {
        if ($from_encoding == '')
            $from_encoding = detect_encoding($string);
    
        if ($from_encoding == $to_encoding)
            return $string;
    
        return mb_convert_encoding($string, $to_encoding, $from_encoding);
    }

    Si su base de datos contiene cadenas de caracteres en 2 diferentes juegos de caracteres, lo que yo haría en su lugar de azotando a todo el código de la aplicación con el conjunto de caracteres de detección /conversión a retorcerse un «one shot» script que va a leer todas las mesas de registros y actualización de sus cadenas en el formato correcto (me gustaría recoger UTF-8 si yo fuera tú). De esta manera el código es más limpio y fácil de mantener.

    Sólo registros de bucle en cada una de las tablas de la base de datos y convertir cadenas como esta:

    //if the 3rd param is not specified the "from encoding" is detected automatically
    $newString = convert_encoding($oldString, 'UTF-8');
  5. 0

    No probé sus muestras aquí, pero a partir de experiencias pasadas, hay una solución rápida para esto. Justo después de la conexión de base de datos ejecute la siguiente consulta ANTES de ejecutar cualquier otra consulta:

    SET NAMES UTF8;

    Este es el Estándar SQL compatible y funciona bien con otras bases de datos, como el pájaro de fuego y PostgreSQL.

    Pero recuerde, usted necesita asegurarse de UTF-8, las declaraciones de otros lugares también con el fin de hacer que su aplicación funciona bien. Sigue una lista de comprobación rápida.

    • Todos los archivos deben ser guardados como UTF-8 (de preferencia sin BOM [Orden de Byte de la Máscara])
    • El Servidor HTTP se debe enviar el encabezado de codificación UTF-8. El uso de Firebug o Live HTTP Headers para inspeccionar.
    • Si su servidor de comprimir y/o acortar la respuesta, puede ver el contenido de la cabecera como fragmentada o gzip. Esto no es un problema si de guardar los archivos como UTF-8 y
    • Declarar la codificación en HTML de la cabecera, el uso correcto de la etiqueta meta.
    • Largo de toda la aplicación (sockets, sistema de archivos, bases de datos…) no te olvides de la bandera hasta UTF-8 cada vez que puede. Hacer esto cuando la apertura de una conexión de base de datos o lo ayuda a usted no necesita codificar/decodificar/depurar todo el tiempo. Agarrar em por raíz.
    • No la dirección de la OP del problema. Él tiene un conjunto de datos con dos mixto codificaciones, y es desconocido para él lo que la fila es la que.
    • Yo veo… me dio una respuesta global. No tan bueno para el caso, y realmente no la dirección de @Lagarto del problema. @Pekka y @Dr. Molle están en el camino correcto. Necesita una función para detectar y convertir como sea necesario.
  6. -1
    1. Lo que base de datos usas?
    2. Usted necesita saber el juego de caracteres de la cadena original antes de convertir a utf-8, si es en el ISO-8859-1 (latin1), a continuación, utf8_encode() es la forma más fácil, de lo contrario deberá utilizar cualquiera icov o mbstring lib convertir y ambas necesitan saber el juego de caracteres de entrada en el fin de convertir correctamente.
    3. Hacer de informar a su base de datos sobre el conjunto de caracteres cuando se introduzca/seleccione los datos?

Dejar respuesta

Please enter your comment!
Please enter your name here