2009-10-29 48 views
7

Estoy tratando de pasar parámetros de un nivel medio PHP a un back-end java que comprende J2EE. Estoy escribiendo el código del controlador en Groovy. Ahí, intento decodificar algún parámetro que probablemente contenga caracteres internacionales.decodificación utf-8 en java

Estoy realmente desconcertado por los resultados de mi depuración de este problema hasta ahora, por lo tanto, quería compartirlo con usted con la esperanza de que alguien será capaz de dar la interpretación correcta de mis resultados.

Por el bien de mi pequeña prueba, el parámetro que estoy pasando es "déjeuner". Sólo para estar seguro, System.out.println ("déjeuner") me da correctamente:

déjeuner 

en la consola

Ahora siguientes son los/dec y hexagonales valores CHAR de cada carbón de leña de la cadena original :

next char: d 100 64 
next char: ? -61 c3 
next char: ? -87 a9 
next char: j 106 6a 
next char: e 101 65 
next char: u 117 75 
next char: n 110 6e 
next char: e 101 65 
next char: r 114 72 

nota que la secuencia c3a9 en UTF-8 es el carácter deseado-para: http://www.fileformat.info/info/unicode/char/00e9/index.htm

Ahora bien, si trato de leer esta cadena como una cadena UTF-8, como en stmt.ge TBytes ("UTF-8"), de repente acaban teniendo una secuencia de 11 bytes, como sigue:

64 c3 83 c2 a9 6a 65 75 6e 65 72 

mientras que stmt.getBytes ("iso-8859-1") me da 9 bytes:

64 c3 a9 6a 65 75 6e 65 72 

¡tenga en cuenta la secuencia c3a9 aquí!

ahora si intento de convertir la secuencia de codificación UTF-8 a UTF-8, como en

new String(stmt.getBytes("UTF-8"), "UTF-8"); 

me sale:

next char: d 100 64 
next char: ? -61 c3 
next char: ? -87 a9 
next char: j 106 6a 
next char: e 101 65 
next char: u 117 75 
next char: n 110 6e 
next char: e 101 65 
next char: r 114 72 

nota la secuencia c3a9

mientras

new String(stmt.getBytes("iso-8859-1"), "UTF-8") 

resultados en:

next char: d 100 64 
next char: ? -23 e9 
next char: j 106 6a 
next char: e 101 65 
next char: u 117 75 
next char: n 110 6e 
next char: e 101 65 
next char: r 114 72 

observe el e9 que en utf-8 (y ascii) es, de nuevo, el carácter 'é' que estoy deseando.

Desafortunadamente, en ninguno de los casos estoy terminando con una cadena adecuada que se muestre como la cadena literal "déjeuner". Curiosamente, las secuencias de bytes parecen correctas.

Respuesta

9

Cuando se trata de cadenas, siempre recuerde: byte! = char. Por lo tanto, en su primer ejemplo, tiene el char c3, no el byte c3, que es una gran diferencia: el byte sería parte de la secuencia UTF-8 pero el charya es Unicode. Entonces cuando lo convierte a UTF-8, el carácter Unicode c3 debe convertirse en la secuencia bytec3 83.

Entonces la pregunta es: ¿Cómo obtuviste el String?Debe haber un error en ese código que no maneja adecuadamente las secuencias byte codificadas en UTF-8.

La razón por la ISO-8859-1 generalmente funciona es que esta codificación no modifica cualquier char con un punto de < 256 (es decir cualquier cosa entre 0 y 255) de código, de modo codificación UTF-8 no serán modificadas byte secuencias.

Su último ejemplo también es incorrecto: el char e9 es é en ISO-8859-1 y Unicode. En UTF-8, no es válido ya que no es un byte y dado que falta el prefijo byte c3. Dicho esto, representa correctamente la cadena Unicode que buscas.

+0

Gracias por la informativa respuesta. Entonces se reduce a request.getParameter() en javax.servlet.http.HttpServletRequest para no manejar correctamente las secuencias de bytes codificadas en UTF-8, ¿verdad? Aunque he llamado a req.setCharacterEncoding ("UTF-8"). ¿Qué posible solución alternativa me queda? Todavía no está claro para mí cómo obtengo los datos originales para mis parámetros (sus bytes, no los caracteres), así que puedo obtener una implementación String _non-buggy_ para resolver la cadena correcta de UTF ... – user162346

+0

Supongo que el remitente codifica los datos con UTF-8, pero no establece los encabezados HTTP correctos para esto. –

+0

Así que asegúrese de que la parte de PHP genere páginas web que especifiquen correctamente su codificación, especialmente en los formularios. –

1

Si comienza con Java String donde "d\u00C3\u00A9jeuner".equals(stmt), entonces los datos ya están corruptos en esta etapa.

Un Java char no es un C char. Un char en Java tiene 16 bits de ancho e implícitamente contiene UTF-16 datos codificados. Intentar almacenar cualquier otro dato codificado en Java char/String es un problema. Los datos de caracteres en cualquier otra codificación deben ser como datos byte.

Si está leyendo parameter using the servlet API, es probable que la solicitud HTTP contenga información de codificación incoherente o insuficiente. Verifique el código de llamada y los encabezados HTTP. Es probable que el cliente esté codificando los datos como UTF-8, pero el servlet está decodificándolo como ISO-8859-1.

0

Tengo un problema muy similar, excepto que mi formulario utiliza la solicitud "OBTENER" no una solicitud "POST".

lo tanto, mi URL es algo así como: http://localhost:4502/form.jsp?query=d%C3%A9jeuner

request.getCharacterEncoding() = ISO-8859-1 
response.getCharacterEncoding() = UTF-8 
request.getParameter("query") = déjeuner 

Así debe al uso HttpServletRequest UTF-8 para descodificar el parámetro petición (que claramente no lo es) o se trata simplemente de un error del navegador ya que el navegador hace no establece ningún encabezado de codificación de caracteres (que de nuevo no tiene mucho sentido porque no está haciendo una solicitud posterior). Aquí está el conjunto completo de encabezados y observe el% C3% A9 en la URL.

http://localhost:4502/form.jsp?query=d%C3%A9juerne 

GET /form.jsp?query=d%C3%A9juerne HTTP/1.1 
Host: localhost:4502 
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.9.0.17) Gecko/2010010604 Ubuntu/9.04 (jaunty) Firefox/3.0.17 
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 
Accept-Language: en-gb,en;q=0.5 
Accept-Encoding: gzip,deflate 
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 
Keep-Alive: 300 
Connection: keep-alive 

Este problema que estoy teniendo es que en realidad copiado y pegado la consulta en el formulario de navegador y de forma incorrecta lo codifica. Tanto en Chrome como en Firefox.

0

Después de algunas investigaciones más me encontré con esta respuesta

How to get UTF-8 working in Java webapps?.

Todo se trata de configurar URIEncoding = "UTF-8" en el conector tomcat.

Ahora vamos a averiguar cómo hacer esto en el CMS que usamos (CQ5/Day).

+0

Hola, bienvenidos a Stackoverflow. ¡No publique sus propias preguntas como respuestas en las preguntas de los demás! Se perderán en el ruido y nadie responderá a tu pregunta. Simplemente publique una pregunta haciendo clic en el botón 'Preguntar' en la parte superior derecha. Una vez hecho esto, elimine este ruido de este tema también. – BalusC