decodificar - utf8_encode array php
Garantizar utf-8 vĂ¡lido en PHP (6)
Estoy usando PHP para manejar el texto de una variedad de fuentes. No anticipo que vaya a ser algo más que UTF-8, ISO-8859-1, o quizás WINDOWS-1252. Si se trata de algo más que uno de esos, solo necesito asegurarme de que el texto se convierta en una cadena UTF-8 válida, incluso si se pierden caracteres. ¿La opción // TRANSLIT de iconv lo soluciona? Por ejemplo, ¿este código aseguraría que una cadena es segura de insertar en un documento codificado UTF-8 (o base de datos)?
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;
}
}
UTF-8 puede almacenar cualquier caracter Unicode. Si su codificación es otra cosa, incluyendo ISO-8859-1 o Windows-1252, UTF-8 puede almacenar cada carácter en ella. Por lo tanto, no tiene que preocuparse por perder ningún carácter al convertir una cadena de cualquier otra codificación a UTF-8.
Además, tanto ISO-8859-1 como Windows-1252 son codificaciones de un solo byte donde cualquier byte es válido. No es técnicamente posible distinguir entre ellos. Elegiría Windows-1252 como su coincidencia predeterminada para secuencias que no sean UTF-8, ya que los únicos bytes que decodifican de manera diferente son el rango 0x80-0x9F. Estos decodifican a varios personajes como comillas inteligentes y al euro en Windows-1252, mientras que en ISO-8859-1 son caracteres de control invisibles que casi nunca se usan. Los navegadores web a veces dicen que están usando ISO-8859-1, pero a menudo usarán Windows-1252.
¿Este código aseguraría que una cadena es segura de insertar en un documento codificado en UTF-8?
Sin duda, querrá establecer el parámetro ''estricto'' opcional en VERDADERO para este propósito. Pero no estoy seguro de que esto realmente cubra todas las secuencias UTF-8 no válidas. La función no pretende verificar una secuencia de bytes para la validez UTF-8 explícitamente. Se han conocido casos en los que mb_detect_encoding adivinaría incorrectamente el UTF-8 anteriormente, aunque no sé si aún puede suceder en modo estricto.
Si quiere estar seguro, hágalo usted mismo usando la expresión regular recomendada por W3 :
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);
Eche un vistazo a http://www.phpwact.org/php/i18n/charsets para obtener una guía sobre los conjuntos de caracteres. Esta página enlaza a una página específica para utf8.
No estoy seguro de si esto lograría lo mismo, pero ¿no podría simplemente usar utf8_encode()
en todo el texto sin preocuparse por la detección? Si el texto ya es UTF-8, no lo dañará. Y si no lo es, se convertirá. Si ya ha pensado en hacer esto, ¿hay algún motivo por el que esto no funcione para usted?
Solo una nota: en lugar de usar la expresión regular frecuentemente recomendada (bastante compleja) del W3C , simplemente puede usar el modificador ''u'' para probar una cadena para la validez de UTF-8:
<?php
if (preg_match("//u", $string)) {
// $string is valid UTF-8
}
respuesta a "iconv es idempotente"
tampoco iconv - iconv no es idempotente
una gran diferencia entre utf8_encode () e iconv () es que iconv puede generar errores como este "Detectó un carácter multibyte incompleto en la cadena de entrada" incluso con
iconv (''ISO-8859-1'', ''UTF-8''. ''// IGNORE'', $ str)
en el código anterior:
$ encoding = mb_detect_encoding ($ string, "UTF-8, ISO-8859-1, WINDOWS-1252");
debes saber que mb_detect_encoding puede responder a uft-8 incluso para cadenas utf-8 no válidas (utf8 mal formado)
Con la biblioteca mbstring , tiene mb_check_encoding () .
Ejemplo de uso:
mb_check_encoding($string, ''UTF-8'');
Cuando el rendimiento importa, esto es más rápido que la expresión regular proporcionada en la respuesta aceptada.
Una prueba rápida en mi configuración muestra (para 20,000 iteraciones):
- expresión regular: ~ 310 ms
- mb_check_encoding: ~ 90 ms
EDITAR
Con PHP 7.1.9 en un sistema Windows 10 reciente, la solución de mb_check_encoding()
regulares supera a mb_check_encoding()
para cualquier longitud de cadena (todavía 20,000 iteraciones):
- 10 caracteres: regex => 4ms,
mb_check_encoding()
=> 64ms - 10000 caracteres: regex => 125ms,
mb_check_encoding()
=> 2.4s