2009-10-01 44 views
6

he recibido esta base de datos completa de los nombres de las personas y los datos en francés, lo que significa que, utilizando caracteres como é, è, o, u, etc. Alrededor de 3.000 entradas.cómo detectar y corregir la codificación de caracteres en una base de datos mysql a través de php?

Aparentemente, los datos en el interior ha sido codificado a veces usando utf8_encode(), y otras no. Esto resulta en una salida desordenada: en algunos lugares los personajes se muestran bien, en otros no.

Al principio traté de rastrear cada lugar en la interfaz de usuario donde surgen esos problemas y uso utf8_decode() cuando sea necesario, pero en realidad no es una solución práctica.

Hice algunas pruebas y no hay ninguna razón para usar utf8_encode en primer lugar, así que preferiría eliminar todo eso y simplemente trabajar en UTF8 en todas partes, en los niveles de navegador, middleware y base de datos. Así que necesito limpiar la base de datos, convirtiendo todos los datos mal codificados por su versión limpia.

Pregunta: ¿sería posible crear una función en php que compruebe si una cadena utf8 está codificada correctamente (sin utf8_encode) o no (con utf8_encode) y, si fuera así, conviértala nuevamente a su estado original ?

En otros términos: me gustaría saber cómo puedo detectar contenido utf8 que ha sido utf8_encode() a contenido utf8 que no ha sido utf8_encode() d.

** ACTUALIZACIÓN: Ejemplo **

Aquí es un buen ejemplo: se toma una cadena completa de caracteres especiales y tomar una copia de esta cadena y utf8_encode() él. La función que estoy soñando toma ambas cuerdas, deja intacta a la primera y la segunda cuerda ahora es igual que la cadena uno.

yo probamos este:

$loc_fr = setlocale(LC_ALL, 'fr_BE.UTF8','[email protected]', 'fr_BE', 'fr', 'fra', 'fr_FR'); 
$str1= "éèöûêïà "; 
$str2 = utf8_encode($str1); 

function convert_charset($str) { 
    $charset= mb_detect_encoding($str); 
    if($charset=="UTF-8") { 
     return utf8_decode($str); 
    } 
    else { 
     return $str; 
    } 
} 
function correctString($str) { 
    echo "\nbefore: $str"; 
    $str= convert_charset($str); 
    echo "\nafter: $str"; 
} 

correctString($str1); 
echo('<hr/>'."\n"); 
correctString($str2); 

Y eso me da:

before: éèöûêïà after: ������� 
before: éèöûêïà after: éèöûêïà 

Gracias,

Alex

Respuesta

6

No está completamente claro por qué objetivo de codificación de caracteres está buscando actualmente (esto depende de los valores predeterminados de su editor de texto, encabezados de navegador, configuración de base de datos, etc.) y qué transformaciones de codificación de caracteres los datos ha pasado a través de. Puede ser que, por ejemplo, al ajustar una configuración de base de datos, todo se corrija, y eso es mucho mejor que hacer cambios parciales en los datos.

Parece que podría ser un problema de doble codificación utf8, y si ese es el caso, tanto la información original como la corrupta estarán en utf8, por lo que la detección de codificación no le proporcionará la información que necesita.El enfoque en ese caso requiere hacer suposiciones sobre qué personajes pueden aparecer razonablemente en sus datos: en lo que concierne a PHP y Mysql "é" es perfectamente legal utf8, por lo que debe hacer un juicio basado en lo que sabe sobre el datos y sus autores que debe estar dañado. Estas son suposiciones arriesgadas si eres solo un técnico. Afortunadamente, si sabe que los datos están en francés y solo hay 3000 registros, probablemente sea correcto hacer ese tipo de suposiciones.

A continuación se muestra una secuencia de comandos que se puede adaptar en primer lugar para verificar sus datos, corregirlos y, finalmente, volver a comprobarlos. Todo lo que hace es procesar una cadena como utf8, dividirla en caracteres y comparar los caracteres con una lista blanca de caracteres franceses esperados. La señal es un problema si la cadena es o no en UTF-8 o contenga caracteres que normalmente no se espera en francés, por ejemplo:

PROBABLY OK  Côte d'Azur 
HAS NON-WHITELISTED CHAR  Côte d'Azur 195,180 ô 
NON-UTF8  C�e d'Azur 

Aquí está la secuencia de comandos, tendrá que descargar las funciones Unicode dependientes de http://hsivonen.iki.fi/php-utf8/

<?php 

// Download from http://hsivonen.iki.fi/php-utf8/ 
require "php-utf8/utf8.inc"; 

$my_french_whitelist = array_merge(
    range(0,127), // throw in all the lower ASCII chars 
    array(
    0xE8, // small e-grave 
    0xE9, // small e-acute 
    0xF4, // small o-circumflex 
    //... Will need to add other accented chars, 
    // Euro sign, and whatever other chars 
    // are normally expected in the data. 
) 
); 

// NB, whether this string literal is in utf8 
// depends on the encoding of the text editor 
// used to write the code 
$str1 = "Côte d'Azur"; 
$test_data = array(
    $str1, 
    utf8_encode($str1), 
    utf8_decode($str1), 
); 

foreach($test_data as $str){ 
    $questionable_chars = non_whitelisted(
    $my_french_whitelist, 
    $str 
); 
    if($questionable_chars===true){ 
    p("NON-UTF8", $str); 
    }else if ($questionable_chars){ 
    p(
     "HAS NON-WHITELISTED CHAR", 
     $str, 
     implode(",", $questionable_chars), 
     unicodeToUtf8($questionable_chars) 
    ); 
    }else{ 
    p("PROBABLY OK", $str); 
    } 
} 

function non_whitelisted($whitelist, $utf8_str){ 
    $codepoints = utf8ToUnicode($utf8_str); 
    if($codepoints===false){ // has non-utf8 char 
    return true; 
    } 
    return array_diff(
    array_unique($codepoints), 
    $whitelist 
); 
} 


function p(){ 
    $args = func_get_args(); 
    echo implode("\t", $args), "\n"; 
} 
+0

Creo que entendiste exactamente el problema, y ​​realmente aprecio tu amplia contribución. Probaré tu script y te responderé. Pregunta: ¿dónde puedo encontrar el código de los otros caracteres acentuados para agregar en la lista blanca? ¿Cómo se llama? ¿Es la columna del código hexadecimal en esta página: http://webdesign.about.com/od/localization/l/blhtmlcodes-fr.htm? – pixeline

+0

Esa lista debe cubrir la mayoría de lo que necesita, y si necesita otros caracteres, se basa en el punto de código Unicode, que puede buscar en alguna parte como http://www.fileformat.info/info/unicode/index.htm . El símbolo del euro podría causar algunos problemas: su punto de código Unicode es U + 20AC, pero ha surgido una convención en HTML de usar una referencia de caracteres de 80, que es lo que usa la lista webdesign.about.com. –

0

Como usted ha dicho que sus datos a veces se convierte usando utf8_encode, sus datos están codificados con UTF-8 o ISO 8859-1 (desde utf8_encode convierte de ISO 8859-1 a UTF-8). Y ya que UTF-8 codifica los caracteres de 128 a 255 con dos bytes que comienzan con 1100001x, sólo hay que comprobar si sus datos es UTF-8 válidos y convertirlo en caso contrario.

Escanee todos sus datos si ya es UTF-8 (vea varias funciones de is_utf8) y use utf8_encode si no es UTF-8.

+0

hi Gumbo, he actualizado mi pregunta con una primera (intento fallido). ¿Puedes mirar y aconsejar? – pixeline

2

Creo que podría estar tomando un enfoque más compilación. Recibí una base de datos búlgara hace unas semanas que estaba codificada dinámicamente en la base de datos, pero cuando la moví a otra base de datos obtuve el funky ???

La forma en que lo resolví fue volcando la base de datos, estableciendo la base de datos en la intercalación utf8 y luego importando los datos como binarios. ¿Esto convirtió automáticamente todo a utf8 y ya no me dio más?

Esto fue en MySQL

+0

mmh, suena bien! ¿Cómo se hace exactamente la parte de "importación de datos como binarios"? ¿Es posible a través de phpmyadmin? – pixeline

+0

Lo siento, me tomó un tiempo responder que estaba fuera. Es posible a través de phpmyadmin http://i38.tinypic.com/1z8cgj.jpg – Gus

+0

Hola Gus. Gracias por volver a mí. Lo intenté y no tuve suerte. Béatrice sigue siendo Béatrice tanto en la base de datos antigua como en la nueva. – pixeline

0

mi problema es que de alguna manera llegué en mis caracteres base de datos como estos a, e, E en formato normal o UTF-8 codificado. Después de la investigación, llegué a la conclusión de que algún navegador (no conozco IE o FF u otro) está codificando los datos de entrada enviados porque no había una codificación utf8 añadida intencionalmente al manejo de los formularios de envío. Entonces, si quisiera leer datos con utf8_encode, alteraré los otros caracteres simples, y viceversa.

Mi solución, después estudié soluciones dadas anteriormente: 1. He creado una nueva base de datos con utf8 2. importado la base de datos después de cambiar la definición charset en CREATE TABLE en el archivo de volcado SQL de América ... a UTF8. 3. importar datos desde la base de datos original (hasta aquí quizás sea suficiente cambiar el conjunto de caracteres en tablas y db existentes, y esto solo si el db original no es utf8) 4. actualizar el contenido en la base de datos directamente reemplazando el utf8 caracteres codificados con no llanura formato algo así como

UPDATE `clients` SET `name` = REPLACE(`name`,"é",'é') WHERE `name` LIKE CONVERT(_latin1 '%é%' USING utf8); 
  1. pongo en clase db (para el código PHP) esta línea para asegurarse de que su es una comunicación UTF8

    $ this-> query ('SET CHARSET UTF8');

Así, ho para actualizar?(Paso 4) he construido una matriz con posibles caracteres que podrían ser codificado

$special_chars = array(
    'ù','û','ü', 
    'ÿ', 
    'à','â','ä','å','æ', 
    'ç', 
    'é','è','ê','ë', 
    'ï','î', 
    'ô','','ö','ó','ø', 
    'ü'); 

He BUIT una matriz con pares de mesa, campo que debe ser actualizado

$where_to_look = array(
    array("table_name" , "field_name"), 
     .....); 

que,

foreach($special_chars as $char) 
    { 
     foreach($where_to_look as $pair) 
     { 
     //$table = $pair[0]; $field = $pair[1] 
     $sql = "SELECT id , `" . $pair[1] . "` FROM " .$pair[0] . " WHERE `" . $pair[1] . "` LIKE CONVERT(_latin1 '%" . $char . "%' USING utf8);"; 

    if($db->num_rows() > 0){ 
     $sql1 = "UPDATE " . $pair[0] . " SET `" . $pair[1] . "` = REPLACE(`" . $pair[1] . "`,CONVERT(_latin1 '" . $char . "' USING utf8),'" . $char . "') WHERE `" . $pair[1] . "` LIKE CONVERT(_latin1 '%" . $char . "%' USING utf8)"; 
     $db1->query($sql1); 
     } 
    } 
} 

La idea pra básica es utilizar funciones de codificación de MySQL para evitar la codificación realiza entre MySQL, Apache, navegador y la espalda; NOTA: No tenía funciones de PHP disponibles como mb _....

Mejor

Cuestiones relacionadas