Este texto de entrada tiene a menudo personajes que son incorrectos para la codificación de salida, cosas como "comillas inteligentes", que provienen de un documento en Windows- 1252 de codificación
“comillas inteligentes” (bytes 147 y 148 en CP1252) son perfectamente caracteres Unicode válidos, U + 201C y U + 201D. Su aplicación debe ser capaz de manejarlos sin problemas; si no, estás haciendo algo mal y muy probablemente todos los caracteres que no sean ASCII fallarán.
Independientemente de si los caracteres provienen de alguien que los escribe o alguien que los pega de Word, el navegador debe enviar caracteres codificados en UTF-8 a su aplicación, que debe almacenar los mismos bytes UTF-8 en la base de datos .
Si el navegador no se envía en UTF-8, es posible que no establezca el juego de caracteres de la página HTML que contiene el formulario.Esto se puede hacer mediante el:
Content-Type: text/html;charset=utf-8
cabecera HTTP y/o el:
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
elemento en < head>.
¿Puedo simplemente establecer el atributo accept-charset en el formulario y hacer que el navegador lo haga por mí?
No, aceptar-charset es básicamente inútil gracias a IE, que malinterpreta que signifique “intente utilizar este conjunto de caracteres, si el de la página no puede codificar los caracteres que queremos”, en lugar de “utilizar siempre este juego de caracteres ". Esto significa que si usa accept-charset puede terminar con una mezcla de codificaciones enviadas a la vez, sin forma de averiguar cuál es cuál. ¡Bonito!
¿por qué mi base de datos está aceptando estos caracteres, que son caracteres reservados/de control en UTF-8?
En MySQL UTF-8 es solo una recopilación, que se utiliza para comparar y ordenar. Todavía está almacenando los datos como bytes y realmente no le importa si no son secuencias UTF-8 válidas.
Es una buena idea decodificar y verificar las secuencias entrantes UTF-8 en su aplicación de todos modos, porque "secuencias cortas", inválidas en Unicode moderno, pueden ocultar un carácter '<' que aún será reconocido por navegadores antiguos (en menos IE6 pre-SP2, Opera 7).
ETA:
Así, entré en una cadena que contiene el byte 146
No, ha introducido un carácter Unicode U + 201B. El navegador trata con caracteres Unicode, no con bytes, hasta el momento en que debe enviar el formulario serializado al servidor. Es entonces cuando decide cómo convertir los caracteres en bytes, y si la página se maneja como UTF-8, siempre elegirá UTF-8.
(Si no es UTF-8, los navegadores tienden a hacer trampa de una manera que no cumple con los estándares: para todos los caracteres que no caben en la codificación, los codificará referencias de caracteres HTML como '& # 8217; '. Esto es incorrecto porque ahora no se puede distinguir entre un' escapado 'del navegador' & 'y un' & 'real, escrito por el usuario, y es insidiosamente incorrecto porque si luego se hace eco de la referencia como HTML no guardado parece que estás haciendo bien, que de hecho se acaba de hacer un agujero de seguridad grande y viejo.)
entró en la base de datos 146
Realmente, un byte '\ x92', no '\ xC2 \ x92', '\ xE2 \ x80 \ x99' o '& # 146;'?
que salió cuando produje el XML (codificado en UTF-8), 146. No hay quejas de que el navegador
Entonces no salió como una sola 146 bytes. Un navegador se quejará cuando se le presente un '\ x92' desnudo en un archivo XML.(No es un archivo HTML, en el que las secuencias UTF-8 no válidas salen como un glifo de caracteres perdidos.)
Sospecho que está saliendo como una referencia de caracteres '& # 146;' que está bien formada (aunque el carácter U + 0092 es parte del conjunto de control C1, por lo tanto no se representará como algo útil). Si esto es lo que está sucediendo, la página de su formulario no está siendo recogida como UTF-8 después de todo, y usted está sufriendo el problema de presentación automática de escaneo del navegador descrito anteriormente.
OK "los bytes 147 y 148 son caracteres Unicode perfectamente válidos, U + 201C y U + 201D" es la parte que no obtengo. El navegador no puede * saber * la codificación de la prueba pegada. ¿Cómo sabe que son cotizaciones inteligentes CP1252? ¡Seguramente son solo bytes! ¿O es el uso de 147-148 tan inusual que es seguro suponer eso? – AmbroseChapel
El navegador no trata con bytes, se trata de caracteres Unicode. Pega caracteres Unicode U + 201C (et al) en un área de texto; el navegador no sabe ni le importa cómo se almacenaron en la aplicación que los copió (lo que probablemente fue Unicode). – bobince
Podría estar * enviando * bytes 147/148, pero eso sería porque cree que la codificación de la página que contiene el formulario era cp1252 y, por lo tanto, la codificación que su formulario quiere obtener es cp1252. Si no le dice lo contrario, puede usar cp1252 (u otras páginas de códigos del sistema en otros países). – bobince