Menú
Gratis
Registro
hogar  /  firmware/ Definición de codificación de texto en PHP y Python. Determinación de codificación de texto PHP: una descripción general de las soluciones existentes más otra bicicleta ¿Qué pasa con PHP?

Determinación de la codificación de texto en PHP y Python. Determinación de codificación de texto PHP: una descripción general de las soluciones existentes más otra bicicleta ¿Qué pasa con PHP?

Había un problema: cómo determinar rápidamente la codificación de una cadena de texto relativa a UTF-8 Cada vez más, debe trabajar con cadenas en codificación UNICODE.

A continuación se muestra una función para verificar si la codificación UNICODE (UTF-8) debe convertirse a la codificación WINDOWS (win-1251)

La función da una respuesta bastante precisa, aunque no se basa en una conversión de código por carácter.

función detect_my_utf($s)( $s=urlencode($s); // operación adicional en algunos casos (coméntelo) $res="0"; $j=strlen($s); $s2=strtoupper($s) ); $s2=str_replace("%D0","",$s2); $s2=str_replace("%D1","",$s2); $k=strlen($s2); $m=1; si ($k>0)( $m=$j/$k; si (($m>1.2)&&($m

Brevemente - descripción de la función detectar_mi_utf():

  • convertir (cadena a formato especial)
  • calcular la longitud de la cadena de entrada
  • convertir todas las letras de una cadena a mayúsculas
  • eliminar códigos específicos %D0 y %D1
  • calcular la longitud de la nueva línea
  • obtener la relación de la línea anterior a la nueva

Si esta relación es 1 o cercana, existe la sospecha de que la cadena entrante no se codificó en UNICODE. Si esta relación está en el rango de 1,2 a 2,2, entonces puede volver a codificar la cadena de forma segura en WINDOWS codificando win-1251.

A la salida de la función, tenemos 0 o 1, respectivamente, no UNICODE o UNICODE.

Ejemplos de ejecución de funciones:

Cadena de entrada: R°R?RyoR?R°S+RyoRyo R? imageready Cadena convertida: %D0%BF%D0%BE%D1%80%D1%8F%D0%B4%D0%BE%D0%BA %D1%81%D0%BE%D0%B7%D0%B4%D0 %B0%D0%BD%D0%B8%D1%8F %D0%B0%D0%BD%D0%B8%D0%BC%D0%B0%D1%86%D0%B8%D0%B8%20%D0 %B2 imageready Resultado de la función: 1 Frase codificada: cómo crear una animación en imageready

Cadena de entrada: R?C?R?R?R?C

Cadena de entrada:

Cadena de entrada: guía de dibujo Cadena convertida: %EF%EE%F1%EE%E1%E8%E5 %EF%EE %F0%E8%F1%EE%E2%E0%ED%E8%FE Resultado de la función: 0 Frase codificada : Tutorial de dibujo Este algoritmo funciona bien con una variedad de cadenas entrantes como parte de un servicio de estadísticas de conversión de motor de búsqueda.

Materiales interesantes en el sitio:

  • Un artículo sobre el interés de búsqueda del sitio. Quizás algunos de los materiales ya estén desactualizados durante 10 años, pero vale la pena prestar atención a algunos puntos.

  • Su opinión sobre el problema del intercambio de hipervínculos entre el sitio donante y el sitio receptor.

  • Otro truco de la vida. Vencimos a los jugadores deshonestos en el juego "Balda". Gran base de datos de palabras que se puede ampliar fácilmente.

Frente a la tarea: detección automática de página/texto/cualquier codificación. La tarea no es nueva y ya se han inventado muchas bicicletas. El artículo contiene una pequeña descripción general de lo que se encontró en la red, además de una oferta propia, que me parece, una solución digna.

1. ¿Por qué no mb_detect_encoding() ?

En resumen, no funciona.

Vamos a mirar:
// En la entrada - Texto en ruso codificado en CP1251 $string = iconv("UTF-8", "Windows-1251", "Se acercó a Anna Pavlovna, le besó la mano, le ofreció su cabeza calva perfumada y brillante, y se sentó tranquilamente en el sofá."); // Veamos que nos da md_detect_encoding(). Primero $estricto = FALSO var_dump(mb_detect_encoding($string, array("UTF-8"))); // UTF-8 var_dump(mb_detect_encoding($string, array("UTF-8", "Windows-1251"))); // Windows-1251 var_dump(mb_detect_encoding($string, array("UTF-8", "KOI8-R"))); // KOI8-R var_dump(mb_detect_encoding($string, array("UTF-8", "Windows-1251", "KOI8-R"))); // FALSO var_dump(mb_detect_encoding($string, array("UTF-8", "ISO-8859-5"))); // ISO-8859-5 var_dump(mb_detect_encoding($string, array("UTF-8", "Windows-1251", "KOI8-R", "ISO-8859-5"))); // ISO-8859-5 // Ahora $estricto = TRUE var_dump(mb_detect_encoding($string, array("UTF-8"), TRUE)); // FALSO var_dump(mb_detect_encoding($string, array("UTF-8", "Windows-1251"), TRUE)); // FALSO var_dump(mb_detect_encoding($string, array("UTF-8", "KOI8-R"), TRUE)); // FALSO var_dump(mb_detect_encoding($string, array("UTF-8", "Windows-1251", "KOI8-R"), TRUE)); // FALSO var_dump(mb_detect_encoding($string, array("UTF-8", "ISO-8859-5"), TRUE)); // ISO-8859-5 var_dump(mb_detect_encoding($string, array("UTF-8", "Windows-1251", "KOI8-R", "ISO-8859-5"), TRUE)); // ISO-8859-5
Como puede ver, la salida es un completo desastre. ¿Qué hacemos cuando no entendemos por qué una función se comporta de esta manera? Así es, buscamos en Google. Encontré una gran respuesta.

Para finalmente disipar todas las esperanzas de usar mb_detect_encoding(), debe ingresar a las fuentes de la extensión mbstring. Entonces, arremangarse, vamos:
// ext/mbstring/mbstring.c:2629 PHP_FUNCTION(mb_detect_encoding) (... // línea 2703 ret = mbfl_identify_encoding_name(&string, elist, size, strict); ...
Ctrl+clic:
// ext/mbstring/libmbfl/mbfl/mbfilter.c:643 const char* mbfl_identify_encoding_name(mbfl_string *string, enum mbfl_no_encoding *elist, int elistsz, int strict) ( const mbfl_encoding *encoding; encoding = mbfl_identify_encoding(string, elist, elistsz , estricto); ...
Ctrl+clic:
// ext/mbstring/libmbfl/mbfl/mbfilter.c:557 /* * identificar la codificación */ const mbfl_encoding * mbfl_identify_encoding(mbfl_string *string, enum mbfl_no_encoding *elist, int elistsz, int strict) ( ...
correo texto completo No usaré el método para no obstruir el artículo con fuentes innecesarias. Aquellos que estén interesados ​​lo verán por sí mismos. Nos interesará la línea número 593, donde se verifica si el carácter se ajusta a la codificación:
// ext/mbstring/libmbfl/mbfl/mbfilter.c:593 (*filtro->función_filtro)(*p, filtro); if (filtro->bandera) ( mal++; )
Estos son los filtros principales para el cirílico de un solo byte:

Windows-1251 (se conservan los comentarios originales)
// ext/mbstring/libmbfl/filters/mbfilter_cp1251.c:142 /* ¡todo esto es tan feo ahora! */ static int mbfl_filt_ident_cp1251(int c, mbfl_identify_filter *filtro) (si (c >= 0x80 && c< 0xff) filter->bandera = 0; otro filtro->

KOI8-R
// ext/mbstring/libmbfl/filters/mbfilter_koi8r.c:142 static int mbfl_filt_ident_koi8r(int c, mbfl_identify_filter *filtro) ( if (c >= 0x80 && c< 0xff) filter->bandera = 0; else filtro->bandera = 1; /* no es */ return c; )

ISO-8859-5 (generalmente todo es divertido aquí)
// ext/mbstring/libmbfl/mbfl/mbfl_ident.c:248 int mbfl_filt_ident_true(int c, mbfl_identify_filter *filtro) ( return c; )
Como puede ver, ISO-8859-5 siempre devuelve VERDADERO (para devolver FALSO, debe establecer filter->flag = 1).

Cuando miramos los filtros, todo encajó. CP1251 es indistinguible de KOI8-R. ISO-8859-5 en general, si está en la lista de codificaciones, siempre se detectará como correcto.

En general, falla. Es comprensible: solo por códigos de caracteres es imposible en el caso general descubrir la codificación, ya que estos códigos se cruzan en diferentes codificaciones.

2. Lo que ofrece Google

Y Google da todo tipo de sordidez. Ni siquiera publicaré la fuente aquí, compruébelo usted mismo si lo desea (elimine el espacio después de http://, no sé cómo mostrar el texto, no como un enlace):

http://deer.org.ua/2009/10/06/1/
http://php.su/forum/topic.php?forum=1&topic=1346

3. Hablar buscar

1) nuevamente códigos de caracteres: habrahabr.ru/blogs/php/27378/#comment_710532

2) en mi opinión, una solución muy interesante: habrahabr.ru/blogs/php/27378/#comment_1399654
Pros y contras en los comentarios en el enlace. Personalmente, creo que esta solución es redundante solo para la detección de codificación; resulta ser demasiado poderosa. La definición de la codificación en él, como efecto secundario).

4. En realidad, mi decisión

La idea surgió al ver el segundo enlace de la sección anterior. La idea es la siguiente: tomamos un texto ruso grande, medimos las frecuencias de diferentes letras y usamos estas frecuencias para detectar la codificación. De cara al futuro, diré de inmediato que habrá problemas con las letras grandes y pequeñas. Por lo tanto, publico ejemplos de frecuencias de letras (llamémoslo "espectro") tanto con mayúsculas como minúsculas (en el segundo caso, agregué una letra aún más grande a la letra minúscula con la misma frecuencia y eliminé todas las grandes). En estos "espectros" se recortan todas las letras con frecuencias inferiores a 0,001 y un espacio. Esto es lo que obtuve después de procesar "Guerra y paz":

"Espectro" sensible a mayúsculas y minúsculas:
array("o" => 0.095249209893009, "e" => 0.06836817536026, "a" => 0.067481298384992, "u" => 0.055995027400041, "n" => 0.052242744063325, ... . "e" => 0.002252892226507, "N " => 0,0021318391371162, "P" => 0,0018574762967903, "f" => 0,0015961610948418, "V" => 0,0014044332975731, "O" => 0,0013188987793209 , "A" => 0,0012623590130186, "K" => 0,0011804488387602, "M" => 0.001061932790165,)

Insensible a mayúsculas y minúsculas:
array("O" => 0.095249209893009, "o" => 0.095249209893009, "E" => 0.06836817536026, "e" => 0.06836817536026, "A" => 0.067481298384992, "a " => 0.067481298384992, "Y" => 0.055995027400041 , "i" => 0.055995027400041, .... "C" => 0.0029893589260344, "c" => 0.0029893589260344, "u" => 0.0024649163501406, "u" => 0.00246491635 01406, "E" => 0.002252892226507, "e " => 0.002252892226507, "Ф" => 0.0015961610948418, "Ф" => 0.0015961610948418,)

Espectros en diferentes codificaciones (claves de matriz - códigos de los caracteres correspondientes en la codificación correspondiente):

Más. Tomamos el texto de una codificación desconocida, para cada codificación que verificamos, encontramos la frecuencia del carácter actual y agregamos esta codificación a la "clasificación". Lo más probable es que la codificación con la calificación más alta sea la codificación de texto.

$codificaciones = array("cp1251" => requiere "specter_cp1251.php", "koi8r" => requiere "specter_koi8r.php", "iso88595" => requiere "specter_iso88595.php"); $tasas_enc = array(); para ($i = 0; $i< len($str); ++$i) { foreach ($encodings as $encoding =>$char_specter) ( $enc_rates[$codificación] += $char_specter)]; ) var_dump($enc_tasas);
Ni siquiera intentes ejecutar este código por tu cuenta, no funcionará. Puede pensar en esto como un pseudocódigo: he omitido los detalles para no abarrotar el artículo. $char_specter son solo las matrices a las que se hace referencia en pastebin.

resultados
Las filas de la tabla son la codificación del texto, las columnas son los contenidos de la matriz $enc_rates.

1) $str = "texto en ruso";
0.441 | 0.020 | 0.085 | Windows-1251
0.049 | 0.441 | 0.166 | KOI8-R
0.133 | 0.092 | 0.441 | ISO-8859-5

Todo esta bien. La codificación real ya tiene una calificación 4 veces más alta que las demás; esto es en un texto tan breve. Para textos más largos, la proporción será más o menos la misma.


cp1251 | koi8r | iso88595 |
0.013 | 0.705 | 0.331 | Windows-1251
0.649 | 0.013 | 0.201 | KOI8-R
0.007 | 0.392 | 0.013 | ISO-8859-5

¡Vaya! Gachas completas. Porque las letras grandes en CP1251 generalmente corresponden a letras pequeñas en KOI8-R. Y las letras pequeñas se usan a su vez con mucha más frecuencia que las grandes. Así que definimos la cadena de mayúsculas en CP1251 como KOI8-R.
Tratando de hacerlo sin distinción entre mayúsculas y minúsculas ("espectros" sin distinción entre mayúsculas y minúsculas)

1) $str = "texto en ruso";
cp1251 | koi8r | iso88595 |
0.477 | 0.342 | 0.085 | Windows-1251
0.315 | 0.477 | 0.207 | KOI8-R
0.216 | 0.321 | 0.477 | ISO-8859-5

2) $str = "STRING CAPSOM RUSSIAN TEXT";
cp1251 | koi8r | iso88595 |
1.074 | 0.705 | 0.465 | Windows-1251
0.649 | 1.074 | 0.201 | KOI8-R
0.331 | 0.392 | 1.074 | ISO-8859-5

Como puede ver, la codificación correcta lidera consistentemente tanto con "espectros" que distinguen entre mayúsculas y minúsculas (si la cadena contiene una pequeña cantidad de letras mayúsculas) como con los que no distinguen entre mayúsculas y minúsculas. En el segundo caso, con los que no distinguen entre mayúsculas y minúsculas, el líder no tiene tanta confianza, por supuesto, pero es bastante estable incluso en cadenas pequeñas. También puede jugar con los pesos de las letras, por ejemplo, hacer que no sean lineales con respecto a la frecuencia.

5. Conclusión

El tema no cubre el trabajo con UTF-8: no hay una diferencia fundamental aquí, excepto que obtener códigos de caracteres y dividir la cadena en caracteres será algo más largo/complicado.
Estas ideas pueden extenderse no solo a las codificaciones cirílicas, por supuesto, la pregunta es solo en los "espectros" de los idiomas/codificación correspondientes.

PD Si es muy necesario/interesante, publicaré la segunda parte de una biblioteca completamente funcional en GitHub. Aunque creo que los datos en la publicación son suficientes para escribir rápidamente una biblioteca de este tipo y satisfacer sus propias necesidades: el "espectro" para el idioma ruso está diseñado, se puede transferir fácilmente a todas las codificaciones necesarias.

Idea - Lotería

No se me ocurrió la idea de obtener la codificación, pero, desafortunadamente, tampoco puedo decirle al autor ahora, ya que fue hace aproximadamente 4 años y se olvidó de dónde obtuve esta información. El autor sugirió una variante de la definición y mostró un ejemplo para 1-2 codificaciones en el lenguaje Python. La sencillez de su solución no me dejó de lado, y la desarrollé hasta el resultado deseado.
La esencia de la idea radica en las propias tablas de codificación. Como sabe, cualquier codificación contiene su propia tabla de códigos y se asigna un valor específico a cada carácter de la codificación. No mostraré tablas de codificación aquí, ahora es bastante fácil encontrarlas en Internet.
El principio de implementación es el siguiente:
  1. Se crea una variable de matriz para almacenar el resultado del "análisis" del texto marcado. Cada elemento de la matriz contendrá el resultado de una codificación particular.
  2. El texto recibido en la entrada de la función se ordena carácter por carácter.
  3. Se toma un ordinal (el valor de ese carácter) de cada carácter y se compara con el rango de codificación.
  4. Si el valor cae en un carácter en mayúscula (mayúscula), el elemento de la matriz que almacena el resultado de esta codificación se establece en 1.
  5. Si el valor cae en un carácter en minúsculas (pequeño), el elemento de la matriz que almacena el resultado de esa codificación se establece en 3.
  6. Esa codificación, más precisamente, ese elemento de la matriz que almacena el resultado de su codificación, que obtuvo la mayor cantidad de puntos, es probablemente la codificación original.
Este algoritmo es válido para codificaciones de un solo byte como KOI-8, CP1251 (windows-1251) y otras. Sin embargo, para las codificaciones de doble byte (en mi caso, UTF-8), este enfoque dará un resultado erróneo. Para empezar, traté de resolver este problema agregando 5 para caracteres en mayúsculas y 7 para caracteres en minúsculas, el resultado mejoró, pero todavía había errores de reconocimiento. Después de un poco de experimentación, llegué a la conclusión de que para la definición correcta de UTF, con caracteres en mayúscula, se debe agregar 10 al resultado, para minúsculas 14, es decir, 2 veces más que mi suposición inicial. Sin embargo, para una mejor comprensión visual del código, dejé 5 y 7 para los caracteres UTF, respectivamente, y ya durante la verificación, estos valores se incrementaron en 2 y se agregaron al resultado.
Eso es básicamente todo el algoritmo. Y sin ninguna molestia adicional.
La mayor parte del tiempo para la implementación de esta función, por supuesto, se dedicó a buscar tablas de códigos y la disposición correcta de rangos. No solo fue bastante difícil encontrar la tabla de códigos real en el momento en que escribí esta función por primera vez, sino que también los rangos de caracteres en ellos saltan al azar. Sin embargo, luego me decidí por las codificaciones más relevantes (hasta el día de hoy): UTF-8, CP1251, KOI8-R, IBM866, ISO-8859-5 y MAC. Si estas codificaciones no son suficientes para usted, puede basarse en este algoritmo agregar código

De las palabras a la práctica

En realidad, el código completo de la función en Python se ve así:

Codificaciones = ( "UTF-8": "utf-8", "CP1251": "windows-1251", "KOI8-R": "koi8-r", "IBM866": "ibm866", "ISO-8859- 5": "iso-8859-5", "MAC": "mac", ) """ Definición de codificación de texto """ def get_codepage(str = Ninguno): mayúsculas = 1 minúsculas = 3 utfupper = 5 utflower = 7 páginas de códigos = () para enc en encodings.keys(): codepages = 0 si str no es None y len(str) > 0: last_simb = 0 para simb en str: simb_ord = ord(simb) """caracteres no rusos" "" si simb_ord< 128 or simb_ord >256: continuar """UTF-8""" si last_simb == 208 y (143< simb_ord < 176 or simb_ord == 129): codepages["UTF-8"] += (utfupper * 2) if (last_simb == 208 and (simb_ord == 145 or 175 < simb_ord < 192)) \ or (last_simb == 209 and (127 < simb_ord < 144)): codepages["UTF-8"] += (utflower * 2) """CP1251""" if 223 < simb_ord < 256 or simb_ord == 184: codepages["CP1251"] += lowercase if 191 < simb_ord < 224 or simb_ord == 168: codepages["CP1251"] += uppercase """KOI8-R""" if 191 < simb_ord < 224 or simb_ord == 163: codepages["KOI8-R"] += lowercase if 222 < simb_ord < 256 or simb_ord == 179: codepages["KOI8-R"] += uppercase """IBM866""" if 159 < simb_ord < 176 or 223 < simb_ord < 241: codepages["IBM866"] += lowercase if 127 < simb_ord < 160 or simb_ord == 241: codepages["IBM866"] += uppercase """ISO-8859-5""" if 207 < simb_ord < 240 or simb_ord == 161: codepages["ISO-8859-5"] += lowercase if 175 < simb_ord < 208 or simb_ord == 241: codepages["ISO-8859-5"] += uppercase """MAC""" if 221 < simb_ord < 255: codepages["MAC"] += lowercase if 127 < simb_ord < 160: codepages["MAC"] += uppercase last_simb = simb_ord idx = "" max = 0 for item in codepages: if codepages >max:max = páginas de códigos idx = devolución de artículo idx
Ejemplo de llamada de función

Imprimir codificaciones

¿Qué pasa con PHP?

No fue difícil reescribir una función ya hecha de Python a PHP. En apariencia, prácticamente no es diferente de su progenitor en Python:

/** * Definir codificación de texto * @param String $texto Texto * @return String Codificación de texto */ function get_codepage($text = "") ( if (!empty($text)) ( $utflower = 7; $utfupper = 5; $minúsculas = 3; $mayúsculas = 1; $last_simb = 0; $juegos de caracteres = array("UTF-8" => 0, "CP1251" => 0, "KOI8-R" => 0, "IBM866" => 0, "ISO-8859-5" => 0, "MAC" => 0,); para ($a = 0; $a< strlen($text); $a++) { $char = ord($text[$a]); // non-russian characters if ($char<128 || $char>256) continuar; // UTF-8 si (($last_simb==208) && (($char>143 && $char<176) || $char==129)) $charsets["UTF-8"] += ($utfupper * 2); if ((($last_simb==208) && (($char>175 && $caracter<192) || $char==145)) || ($last_simb==209 && $char>127 && $caracter<144)) $charsets["UTF-8"] += ($utflower * 2); // CP1251 if (($char>223 && $caracter<256) || $char==184) $charsets["CP1251"] += $lowercase; if (($char>191 && $caracter<224) || $char==168) $charsets["CP1251"] += $uppercase; // KOI8-R if (($char>191 && $caracter<224) || $char==163) $charsets["KOI8-R"] += $lowercase; if (($char>222 && $caracter<256) || $char==179) $charsets["KOI8-R"] += $uppercase; // IBM866 if (($char>159 && $caracter<176) || ($char>223 && $caracter<241)) $charsets["IBM866"] += $lowercase; if (($char>127 && $caracter<160) || $char==241) $charsets["IBM866"] += $uppercase; // ISO-8859-5 if (($char>207 && $caracter<240) || $char==161) $charsets["ISO-8859-5"] += $lowercase; if (($char>175 && $caracter<208) || $char==241) $charsets["ISO-8859-5"] += $uppercase; // MAC if ($char>221 && $caracter<255) $charsets["MAC"] += $lowercase; if ($char>127 && $caracter<160) $charsets["MAC"] += $uppercase; $last_simb = $char; } arsort($charsets); return key($charsets); } }
Ejemplo de llamada de función

echo get_codepage(file_get_contents("test.txt"));

Likbez, o no interfiera con la máquina para trabajar

No debe intentar hacer una prueba de choque de esta función. Está claro del algoritmo que cuanto menos texto recibe como entrada, más probable es que la función reconozca la codificación incorrectamente. Por otro lado, alimentar volúmenes de León Tolstoi tampoco tiene sentido: este método hace un trabajo excelente con una oración pequeña de 100 a 200 caracteres. Y aunque en los ejemplos de la llamada a la entrada envié todo el contenido de un determinado archivo "test.txt", que asumía que hay texto cuya codificación debe determinarse, un pequeño fragmento de texto puede (y debe) ser pasa a la entrada de la función.
Las perversiones con letras mayúsculas y minúsculas mixtas generalmente no son apropiadas en este caso, ya que este método fue escrito para una tarea ordinaria ordinaria con un ruso aproximadamente alfabetizado. Y tales experimentos a menudo me recuerdan una broma:

Una planta de carpintería rusa compró una máquina japonesa. Los trabajadores rusos se reunieron a su alrededor y averigüemos cómo trabaja. Uno tomó el tablero, lo puso en él. Unidad: zzzzzzzzzzzzzzzzin... A la salida, un taburete confeccionado. Chicos: ¡Nada en sí mismo! La unidad en la pantalla: bueno, ¿qué te pareció? Otro tomó un tronco sin tallar y lo insertó en la unidad. Unidad: zzzzzzzzzzzzzzzz... A la salida, un aparador tallado está listo. Chicos: ¡Nada en sí mismo! La unidad en la pantalla: bueno, ¿qué te pareció? El tercer hombre no pudo soportarlo, sacó el riel de algún lado y lo metió en la unidad. La unidad: drrrrr-tyh-tyh-tyh ... Fumó y la inscripción en la pantalla: ¡Nada para sí mismo! Chicos: Bueno, ¿qué pensaste?
Entonces, para tales pruebas perversas, lo más probable es que necesite un algoritmo perverso, que no es esta función. Y por la práctica diré que durante el uso durante 4 años, este método nunca me ha fallado y siempre dio el resultado correcto.
Espero que mi artículo sea útil para alguien.
Gracias por su atención.

Cuando uses todo o parte del contenido, no olvides enlazar a la fuente, es decir, a mi blog.

Frente a la tarea: detección automática de página/texto/cualquier codificación. La tarea no es nueva y ya se han inventado muchas bicicletas. El artículo contiene una pequeña descripción general de lo que se encontró en la red, además de una oferta propia, que me parece, una solución digna.

1. ¿Por qué no mb_detect_encoding() ?

En resumen, no funciona.

Vamos a mirar:
// En la entrada - Texto en ruso codificado en CP1251 $string = iconv("UTF-8", "Windows-1251", "Se acercó a Anna Pavlovna, le besó la mano, le ofreció su cabeza calva perfumada y brillante, y se sentó tranquilamente en el sofá."); // Veamos que nos da md_detect_encoding(). Primero $estricto = FALSO var_dump(mb_detect_encoding($string, array("UTF-8"))); // UTF-8 var_dump(mb_detect_encoding($string, array("UTF-8", "Windows-1251"))); // Windows-1251 var_dump(mb_detect_encoding($string, array("UTF-8", "KOI8-R"))); // KOI8-R var_dump(mb_detect_encoding($string, array("UTF-8", "Windows-1251", "KOI8-R"))); // FALSO var_dump(mb_detect_encoding($string, array("UTF-8", "ISO-8859-5"))); // ISO-8859-5 var_dump(mb_detect_encoding($string, array("UTF-8", "Windows-1251", "KOI8-R", "ISO-8859-5"))); // ISO-8859-5 // Ahora $estricto = TRUE var_dump(mb_detect_encoding($string, array("UTF-8"), TRUE)); // FALSO var_dump(mb_detect_encoding($string, array("UTF-8", "Windows-1251"), TRUE)); // FALSO var_dump(mb_detect_encoding($string, array("UTF-8", "KOI8-R"), TRUE)); // FALSO var_dump(mb_detect_encoding($string, array("UTF-8", "Windows-1251", "KOI8-R"), TRUE)); // FALSO var_dump(mb_detect_encoding($string, array("UTF-8", "ISO-8859-5"), TRUE)); // ISO-8859-5 var_dump(mb_detect_encoding($string, array("UTF-8", "Windows-1251", "KOI8-R", "ISO-8859-5"), TRUE)); // ISO-8859-5
Como puede ver, la salida es un completo desastre. ¿Qué hacemos cuando no entendemos por qué una función se comporta de esta manera? Así es, buscamos en Google. Encontré una gran respuesta.

Para finalmente disipar todas las esperanzas de usar mb_detect_encoding(), debe ingresar a las fuentes de la extensión mbstring. Entonces, arremangarse, vamos:
// ext/mbstring/mbstring.c:2629 PHP_FUNCTION(mb_detect_encoding) (... // línea 2703 ret = mbfl_identify_encoding_name(&string, elist, size, strict); ...
Ctrl+clic:
// ext/mbstring/libmbfl/mbfl/mbfilter.c:643 const char* mbfl_identify_encoding_name(mbfl_string *string, enum mbfl_no_encoding *elist, int elistsz, int strict) ( const mbfl_encoding *encoding; encoding = mbfl_identify_encoding(string, elist, elistsz , estricto); ...
Ctrl+clic:
// ext/mbstring/libmbfl/mbfl/mbfilter.c:557 /* * identificar la codificación */ const mbfl_encoding * mbfl_identify_encoding(mbfl_string *string, enum mbfl_no_encoding *elist, int elistsz, int strict) ( ...
No publicaré el texto completo del método, para no obstruir el artículo con fuentes innecesarias. Aquellos que estén interesados ​​lo verán por sí mismos. Nos interesará la línea número 593, donde se verifica si el carácter se ajusta a la codificación:
// ext/mbstring/libmbfl/mbfl/mbfilter.c:593 (*filtro->función_filtro)(*p, filtro); if (filtro->bandera) ( mal++; )
Estos son los filtros principales para el cirílico de un solo byte:

Windows-1251 (se conservan los comentarios originales)
// ext/mbstring/libmbfl/filters/mbfilter_cp1251.c:142 /* ¡todo esto es tan feo ahora! */ static int mbfl_filt_ident_cp1251(int c, mbfl_identify_filter *filtro) (si (c >= 0x80 && c< 0xff) filter->bandera = 0; otro filtro->

KOI8-R
// ext/mbstring/libmbfl/filters/mbfilter_koi8r.c:142 static int mbfl_filt_ident_koi8r(int c, mbfl_identify_filter *filtro) ( if (c >= 0x80 && c< 0xff) filter->bandera = 0; else filtro->bandera = 1; /* no es */ return c; )

ISO-8859-5 (generalmente todo es divertido aquí)
// ext/mbstring/libmbfl/mbfl/mbfl_ident.c:248 int mbfl_filt_ident_true(int c, mbfl_identify_filter *filtro) ( return c; )
Como puede ver, ISO-8859-5 siempre devuelve VERDADERO (para devolver FALSO, debe establecer filter->flag = 1).

Cuando miramos los filtros, todo encajó. CP1251 es indistinguible de KOI8-R. ISO-8859-5 en general, si está en la lista de codificaciones, siempre se detectará como correcto.

En general, falla. Es comprensible: solo por códigos de caracteres es imposible en el caso general descubrir la codificación, ya que estos códigos se cruzan en diferentes codificaciones.

2. Lo que ofrece Google

Y Google da todo tipo de sordidez. Ni siquiera publicaré la fuente aquí, compruébelo usted mismo si lo desea (elimine el espacio después de http://, no sé cómo mostrar el texto, no como un enlace):

http://deer.org.ua/2009/10/06/1/
http://php.su/forum/topic.php?forum=1&topic=1346

3. Hablar buscar

1) de nuevo códigos de caracteres:

2) en mi opinión, una solución muy interesante:
Pros y contras en los comentarios en el enlace. Personalmente, creo que esta solución es redundante solo para la detección de codificación; resulta ser demasiado poderosa. La definición de la codificación en él, como efecto secundario).

4. En realidad, mi decisión

La idea surgió al ver el segundo enlace de la sección anterior. La idea es la siguiente: tomamos un texto ruso grande, medimos las frecuencias de diferentes letras y usamos estas frecuencias para detectar la codificación. De cara al futuro, diré de inmediato que habrá problemas con las letras grandes y pequeñas. Por lo tanto, publico ejemplos de frecuencias de letras (llamémoslo "espectro") tanto con mayúsculas como minúsculas (en el segundo caso, agregué una letra aún más grande a la letra minúscula con la misma frecuencia y eliminé todas las grandes). En estos "espectros" se recortan todas las letras con frecuencias inferiores a 0,001 y un espacio. Esto es lo que obtuve después de procesar "Guerra y paz":

"Espectro" sensible a mayúsculas y minúsculas:
array("o" => 0.095249209893009, "e" => 0.06836817536026, "a" => 0.067481298384992, "u" => 0.055995027400041, "n" => 0.052242744063325, ... . "e" => 0.002252892226507, "N " => 0,0021318391371162, "P" => 0,0018574762967903, "f" => 0,0015961610948418, "V" => 0,0014044332975731, "O" => 0,0013188987793209 , "A" => 0,0012623590130186, "K" => 0,0011804488387602, "M" => 0.001061932790165,)

Insensible a mayúsculas y minúsculas:
array("O" => 0.095249209893009, "o" => 0.095249209893009, "E" => 0.06836817536026, "e" => 0.06836817536026, "A" => 0.067481298384992, "a " => 0.067481298384992, "Y" => 0.055995027400041 , "i" => 0.055995027400041, .... "C" => 0.0029893589260344, "c" => 0.0029893589260344, "u" => 0.0024649163501406, "u" => 0.00246491635 01406, "E" => 0.002252892226507, "e " => 0.002252892226507, "Ф" => 0.0015961610948418, "Ф" => 0.0015961610948418,)

Espectros en diferentes codificaciones (claves de matriz - códigos de los caracteres correspondientes en la codificación correspondiente):

Más. Tomamos el texto de una codificación desconocida, para cada codificación que verificamos, encontramos la frecuencia del carácter actual y agregamos esta codificación a la "clasificación". Lo más probable es que la codificación con la calificación más alta sea la codificación de texto.

$codificaciones = array("cp1251" => requiere "specter_cp1251.php", "koi8r" => requiere "specter_koi8r.php", "iso88595" => requiere "specter_iso88595.php"); $tasas_enc = array(); para ($i = 0; $i< len($str); ++$i) { foreach ($encodings as $encoding =>$char_specter) ( $enc_rates[$codificación] += $char_specter)]; ) var_dump($enc_tasas);
Ni siquiera intentes ejecutar este código por tu cuenta, no funcionará. Puede pensar en esto como un pseudocódigo: he omitido los detalles para no abarrotar el artículo. $char_specter son solo las matrices a las que se hace referencia en pastebin.

resultados
Las filas de la tabla son la codificación del texto, las columnas son los contenidos de la matriz $enc_rates.

1) $str = "texto en ruso";
0.441 | 0.020 | 0.085 | Windows-1251
0.049 | 0.441 | 0.166 | KOI8-R
0.133 | 0.092 | 0.441 | ISO-8859-5

Todo esta bien. La codificación real ya tiene una calificación 4 veces más alta que las demás; esto es en un texto tan breve. Para textos más largos, la proporción será más o menos la misma.


cp1251 | koi8r | iso88595 |
0.013 | 0.705 | 0.331 | Windows-1251
0.649 | 0.013 | 0.201 | KOI8-R
0.007 | 0.392 | 0.013 | ISO-8859-5

¡Vaya! Gachas completas. Porque las letras grandes en CP1251 generalmente corresponden a letras pequeñas en KOI8-R. Y las letras pequeñas se usan a su vez con mucha más frecuencia que las grandes. Así que definimos la cadena de mayúsculas en CP1251 como KOI8-R.
Tratando de hacerlo sin distinción entre mayúsculas y minúsculas ("espectros" sin distinción entre mayúsculas y minúsculas)

1) $str = "texto en ruso";
cp1251 | koi8r | iso88595 |
0.477 | 0.342 | 0.085 | Windows-1251
0.315 | 0.477 | 0.207 | KOI8-R
0.216 | 0.321 | 0.477 | ISO-8859-5

2) $str = "STRING CAPSOM RUSSIAN TEXT";
cp1251 | koi8r | iso88595 |
1.074 | 0.705 | 0.465 | Windows-1251
0.649 | 1.074 | 0.201 | KOI8-R
0.331 | 0.392 | 1.074 | ISO-8859-5

Como puede ver, la codificación correcta lidera consistentemente tanto con "espectros" que distinguen entre mayúsculas y minúsculas (si la cadena contiene una pequeña cantidad de letras mayúsculas) como con los que no distinguen entre mayúsculas y minúsculas. En el segundo caso, con los que no distinguen entre mayúsculas y minúsculas, el líder no tiene tanta confianza, por supuesto, pero es bastante estable incluso en cadenas pequeñas. También puede jugar con los pesos de las letras, por ejemplo, hacer que no sean lineales con respecto a la frecuencia.

5. Conclusión

El tema no cubre el trabajo con UTF-8: no hay una diferencia fundamental aquí, excepto que obtener códigos de caracteres y dividir la cadena en caracteres será algo más largo/complicado.
Estas ideas pueden extenderse no solo a las codificaciones cirílicas, por supuesto, la pregunta es solo en los "espectros" de los idiomas/codificación correspondientes.

PD Si es muy necesario/interesante, publicaré la segunda parte de una biblioteca completamente funcional en GitHub. Aunque creo que los datos en la publicación son suficientes para escribir rápidamente una biblioteca de este tipo y satisfacer sus propias necesidades: el "espectro" para el idioma ruso está diseñado, se puede transferir fácilmente a todas las codificaciones necesarias.

Leo muchos textos de diferentes fuentes RSS y los inserto en mi base de datos.

Por supuesto, hay varias codificaciones de caracteres diferentes que se utilizan en los canales, p. UTF-8 e ISO-8859-1.

Desafortunadamente, a veces hay problemas con las codificaciones de texto. Ejemplo:

1) "ß" en "Fußball" debería verse así en mi base de datos: "Ÿ". Si es "Ÿ", se muestra correctamente.

2) A veces, la "ß" en "Fußball" se ve así en mi base de datos: "ß". Entonces se muestra incorrectamente, por supuesto.

3) En otros casos, "ß" se almacena como "ß", por lo tanto, sin ningún cambio. Entonces también se muestra incorrectamente.

¿Qué puedo hacer para evitar los casos 2 y 3?

¿Cómo puedo hacer que todo tenga la misma codificación, preferiblemente UTF-8? ¿Cuándo debo usar utf8_encode(), cuándo debo usar utf8_decode() (está claro cuál es el efecto, pero cuándo debo usar funciones?) y cuándo debo hacer algo con la entrada.

¿Pueden ayudarme y decirme cómo hacer todos los mismos códigos? ¿Quizás con la función mb-detect-encoding()? ¿Puedo escribir una función para esto? Entonces, mis problemas son: 1) Cómo averiguar qué codificación se usa en el texto 2) Cómo convertirlo a UTF-8, independientemente de la codificación anterior

EDITAR:¿Funcionaría tal función?

Función codificación_correcta($texto) ( $codificación_actual = mb_detect_encoding($texto, "auto"); $texto = iconv($codificación_actual, "UTF-8", $texto); return $texto; )

Lo probé pero no funciona. ¿Lo que está mal con él?

24 respuestas

Si aplica utf8_encode() a una cadena UTF8 ya existente, devolverá una salida UTF8 alterada.

Creé una función que soluciona todos estos problemas. Se llama Codificación::toUTF8().

No necesita saber cuál es la codificación de sus cadenas. Puede ser Latin1 (iso 8859-1), Windows-1252 o UTF8, o la cadena puede contenerlos. Encoding::toUTF8() convertirá todo a UTF8.

Hice esto porque el servicio me estaba dando un flujo de datos, todo desordenado, mezclando UTF8 y Latin1 en la misma línea.

Uso:

Require_once("Codificación.php"); use \ForceUTF8\Encoding; // Tiene un espacio de nombres ahora. $utf8_string = Codificación::toUTF8($utf8_or_latin1_or_mixed_string); $latin1_string = Codificación::toLatin1($utf8_or_latin1_or_mixed_string);

Incluí otra función, Encoding::fixUFT8(), que corregirá todas las cadenas UTF8 que parezcan mal formadas.

Uso:

Require_once("Codificación.php"); use \ForceUTF8\Encoding; // Tiene un espacio de nombres ahora. $utf8_string = Codificación::fixUTF8($ilegible_utf8_string);

Codificación de eco::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");

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

Actualización: he convertido la función (forceUTF8) en una familia de funciones estáticas en la clase de codificación. Nueva caracteristica- Codificación::toUTF8().

Primero debe determinar qué codificación se utilizó. Dado que está analizando fuentes RSS (quizás a través de HTTP), debe leer la codificación del parámetro charset del campo Tipo de contenido del encabezado HTTP. Si falta, lea la codificación del atributo de codificación de la instrucción de procesamiento. Si eso también falta, use UTF-8 como se define en la especificación.

Cambiar Esto es lo que probablemente haré:

La detección de codificación es difícil.

mb_detect_encoding funciona adivinando entre varios candidatos que aprueba. En algunas codificaciones, ciertas secuencias de bytes no son válidas, por lo que puede distinguir entre diferentes candidatos. Desafortunadamente, hay muchas codificaciones donde los mismos bytes son válidos (pero diferentes). En estos casos, no es posible determinar la codificación; Puede implementar su propia lógica para hacer conjeturas en estos casos. Por ejemplo, es probable que los datos provenientes de un sitio japonés estén codificados en japonés.

Si bien solo se trata de idiomas de Europa occidental, considere las tres codificaciones principales: utf-8 , iso-8859-1 y cp-1252 . Debido a que son los valores predeterminados para muchas plataformas, también es probable que se informen incorrectamente. Por ejemplo. si las personas usan codificaciones diferentes, probablemente serán francos al respecto porque, de lo contrario, sus software se romperá muy a menudo. Por lo tanto, es una buena estrategia confiar en el proveedor, a menos que la codificación se declare como una de esas tres. Todavía tiene que duplicar que es realmente válido usando mb_check_encoding (tenga en cuenta que válido no es lo mismo que ser: la misma entrada puede ser válida para muchas codificaciones). Si es uno de ellos, puede usar mb_detect_encoding para distinguirlos. Afortunadamente, esto es bastante determinista; Solo necesita usar la secuencia de detección correcta, que es UTF-8,ISO-8859-1,WINDOWS-1252.

Una vez que haya encontrado la codificación, debe convertirla a su representación interna (utf-8 es la única Elección inteligente). La función utf8_encode convierte iso-8859-1 a utf-8, por lo que solo se puede usar para ese tipo de entrada en particular. Para otras codificaciones, use mb_convert_encoding.

Esta hoja de trucos enumera algunas advertencias comunes relacionadas con el manejo de PHP de UTF-8: http://developer.loftdigital.com/blog/php-utf-8-cheatsheet

Esta función, que detecta caracteres multibyte en una cadena, también puede ser útil ():

Función detectUTF8($string) ( return preg_match("%(?: [\xC2-\xDF][\x80-\xBF] # 2 bytes no demasiado largos |\xE0[\xA0-\xBF][\x80- \xBF] # excluyendo overlongs |[\xE1-\xEC\xEE\xEF][\x80-\xBF](2) # directo de 3 bytes |\xED[\x80-\x9F][\x80-\xBF] # excluyendo sustitutos |\xF0[\x90-\xBF][\x80-\xBF](2) # planos 1-3 |[\xF1-\xF3][\x80-\xBF](3) # planos 4- 15 |\xF4[\x80-\x8F][\x80-\xBF](2) # plano 16)+%xs", $cadena); )

Un pequeño aviso, dijiste que "ß" debería aparecer como "Ÿ" en tu base de datos.

Probablemente se deba a que está utilizando una base de datos con codificación de caracteres latin1, o tal vez la conexión php-mysql esté mal configurada, php cree que su mysql está configurado para usar utf-8, por lo que envía datos como utf8, pero su mysql cree que php envía datos codificado como iso-8859-1, por lo que podría intentar codificar los datos enviados como utf-8 nuevamente, causando problemas como este.

Echa un vistazo a esto, podría ayudarte: http://php.net/manual/en/function.mysql-set-charset.php

Debe verificar la codificación en la entrada, ya que las respuestas se pueden codificar con diferentes codificaciones.
Obligo a que todo el contenido se envíe en UTF-8 haciendo detección y traducción usando la siguiente función:

Función fixRequestCharset() ( $ref = array(&$_GET, &$_POST, &$_REQUEST); foreach ($ref as &$var) ( foreach ($var as $key => $val) ( $encoding = mb_detect_encoding ($var[ $clave], mb_detect_order(), true); if (!$codificación) continuar; if (strcasecmp($codificación, "UTF-8") != 0) ( $codificación = iconv($codificación, " UTF-8", $var[ $clave ]); if ($codificación === falso) continuar; $var[ $clave ] = $codificación; ) ) ) )

Este procedimiento convertirá todo Variables PHP, que provienen del host remoto en UTF-8.
O ignore el valor si la codificación no se puede detectar o convertir.
Puedes personalizarlo según tus necesidades.
Simplemente llámelo antes de usar variables.

Su codificación parece estar codificada en UTF-8 dos veces; es decir, desde alguna otra codificación, a UTF-8 y nuevamente a UTF-8. Como si tuviera iso-8859-1 convertido de iso-8859-1 a utf-8 y analizado nueva línea como iso-8859-1 para otra conversión a UTF-8.

Aquí hay un pseudo código para lo que hiciste:

$cadena de entrada = getFromUser(); $utf8string = iconv($current_encoding, "utf-8", $inputstring); $cadena defectuosa = iconv($codificación_actual, "utf-8", $utf8cadena);

Debes intentar:

  • detecta la codificación con mb_detect_encoding() o lo que quieras usar
  • si es UTF-8, convierta a iso-8859-1 y repita el paso 1
  • finalmente convertir de nuevo a UTF-8

Se supone que usó iso-8859-1 en la conversión "media". Si usó Windows-1252, conviértalo a Windows-1252 (latin1). La codificación de la fuente original no es importante; el que usó en la segunda conversión errónea.

Esta es mi suposición de lo que sucedió; podría hacer un poco más para obtener cuatro bytes en lugar de un byte ASCII extendido.

El alemán también usa iso-8859-2 y windows-1250 (latin2).

El desarrollo de la codificación de caracteres de fuentes RSS parece complejo. Incluso las páginas web normales a menudo omiten o mienten sobre su codificación.

Por lo tanto, puede intentar usar la forma de detección de codificación correcta y luego recurrir a alguna forma de detección automática (adivinanzas).

Sé que esta es una vieja pregunta, pero creo que una respuesta útil nunca está de más. Tengo problemas con mi codificación entre aplicaciones de escritorio, SQLite y variables GET/POST. Parte estará en UTF-8, parte estará en ASCII y, básicamente, las cosas se confundirán cuando se trate de caracteres extranjeros.

Aquí está mi solución. Aplana su GET/POST/REQUEST (me perdí galletas, pero puede agregarlos si es necesario) en cada carga de página antes de procesar. Funciona bien en el encabezado. PHP emitirá advertencias si no puede determinar automáticamente la codificación de origen, por lo que estas advertencias se suprimen con @.

//Convertir todo en nuestros vars a UTF-8 para jugar bien con la base de datos... //Usar algo de detección automática aquí para ayudarnos a no codificar dos veces... //Suprimir posibles advertencias con @ para cuando no se pueda detectar la codificación intente ( $proceso = matriz(&$_GET, &$_POST, &$_REQUEST); while (lista($clave, $val) = each($proceso)) ( foreach ($val as $k => $v) ( unset($proceso[$clave][$k]); if (is_array($v)) ( $proceso[$clave][@mb_convert_encoding($k,"UTF-8","auto")] = $ v; $proceso = &$proceso[$clave][@mb_convert_encoding($k,"UTF-8","auto")]); ) else ($proceso[$clave][@mb_convert_encoding($k,"UTF- 8","auto")] = @mb_convert_encoding($v,"UTF-8","auto"); ) ) ) unset($proceso); ) catch(Exception $ex)()

¡He estado revisando soluciones de codificación con AGES y esta página es probablemente el final de años de búsqueda! Probé algunas de las sugerencias que mencionaste y aquí están mis notas:

Esta es mi cadena de prueba:

esta es la cadena "mal escrito" que no usé para personalización especial chàrs para verlos, convertidos por fùnctìon!! ¡Entonces qué es esto!

La fuente de mi página es UTF-8

Si hago el INSERTAR de esta manera, tengo algunos caracteres en mi base de datos que probablemente provengan de Marte... así que necesito convertirlos a UTF-8 "cuerdo". Intenté utf8_encode() pero todavía los personajes alienígenas invadían mi base de datos...

Entonces, traté de usar la función forceUTF8 publicada en el número 8, pero en la base de datos, la cadena guardada se ve así:

es la cadena "wròng wrìtten" bùt i nèed to pù "sà ²me" special chà rs to see thèm, convertèd by fùnctìon!! ¡Entonces qué es esto!

Entonces, al recopilar más información en esta página y combinarla con otra información en otras páginas, resolví el problema con esta solución:

$finallyIDidIt = mb_convert_encoding($string, mysql_client_encoding($resourceID), mb_detect_encoding($string));

Ahora en mi base de datos tengo una cadena con la codificación correcta.

Nota:¡Solo tenga en cuenta que debe cuidar la función mysql_client_encoding! Debe estar conectado a la base de datos porque esta función requiere una identificación de recurso como parámetro.

Pero está bien, solo hago esta recodificación antes de mi INSERCIÓN, por lo que no es un problema para mí.

Espero que esto ayude a alguien como esta página me ayudó!

¡Gracias a todos!

Lo interesante de mb_detect_encoding y mb_convert_encoding es que el orden de las codificaciones que sugiere es importante:

// $entrada es en realidad UTF-8 mb_detect_encoding($entrada, "UTF-8", "ISO-8859-9, UTF-8"); // ISO-8859-9 (¡INCORRECTO!) mb_detect_encoding($input, "UTF-8", "UTF-8, ISO-8859-9"); // UTF-8 (bien)

Por lo tanto, puede usar un orden específico al especificar las codificaciones esperadas. Sin embargo, tenga en cuenta que esto no es confiable.

echo mb_detect_encoding($str, "auto");

echo mb_detect_encoding($str, "UTF-8, ASCII, ISO-8859-1");

Realmente no sé cuáles son los resultados, pero le sugiero que tome algunos de sus feeds con diferentes codificaciones y pruebe si mb_detect_encoding funciona o no.

Actualizar
auto es la abreviatura de "ASCII, JIS, UTF-8, EUC-JP, SJIS". devuelve la codificación detectada, que puede usar para convertir la cadena a utf-8 con iconv .

No lo he probado, así que no hay garantías. y tal vez hay una manera más fácil.

Esta versión es para alemán, pero puede modificar $CHARSETS y $TESTCHARS

Class CharsetDetector ( $CHARSETS estáticos privados = array("ISO_8859-1", "ISO_8859-15", "CP850"); $TESTCHARS estáticos privados = array("€", "ä", "Ä", "ö", "Ö", "ü", "Ü", "ß"); función estática pública convertir ($cadena) ( return self::__iconv($cadena, self::getCharset($cadena)); ) función estática pública getCharset ($cadena) ( $normalizado = self::__normalize($cadena); if(!strlen($normalizado))return "UTF-8"; $mejor = "UTF-8"; $charcountbest = 0; foreach (self ::$CHARSETS as $charset) ( $str = self::__iconv($normalizado, $charset); $charcount = 0; $stop = mb_strlen($str, "UTF-8"); for($idx = 0 ;$idx< $stop; $idx++) { $char = mb_substr($str, $idx, 1, "UTF-8"); foreach (self::$TESTCHARS as $testchar) { if($char == $testchar) { $charcount++; break; } } } if($charcount>$charcountbest) ( $charcountbest=$charcount; $best=$charset; ) //eco $texto".
"; ) devuelve $mejor; ) función estática privada __normalize($str) ( $len = strlen($str); $ret = ""; for($i = 0; $i< $len; $i++){ $c = ord($str[$i]); if ($c >128) ( if (($c > 247)) $ret .=$str[$i]; elseif ($c > 239) $bytes = 4; elseif ($c > 223) $bytes = 3; elseif ($ c > 191) $bytes = 2; else $ret .=$str[$i]; if (($i + $bytes) > $len) $ret .=$str[$i]; $ret2=$str [$i]; while ($bytes > 1) ( $i++; $b = ord($str[$i]); if ($b< 128 || $b >191) ($ret .=$ret2; $ret2=""; $i+=$bytes-1;$bytes=1; break;) else $ret2.=$str[$i]; $bytes--; ) ) ) devuelve $ret; ) función estática privada __iconv($string, $charset) (return iconv ($charset, "UTF-8", $string); ) )

Después de ordenar sus scripts php, no olvide decirle a mysql qué codificación está pasando y le gustaría obtenerla.

Ejemplo: configuración del conjunto de caracteres en utf8

Pasar datos de utf8 a la tabla latin1 en la sesión de E/S de latin1 genera esos molestos pájaros. Veo esto todos los días en las tiendas minoristas. De ida y vuelta puede parecer correcto. Pero phpmyadmin mostrará la verdad. Decirle a mysql qué codificación está pasando se manejará datos mysql para ti.

Cómo recuperar datos mysql codificados existentes es otra pregunta para discutir. :)