Está en la página 1de 8

Juegos de Caracteres

Publicado el 19 March, 2012 por Movired Este artculo describe las consideraciones a tener en cuenta en relacin a los juegos de caracteres empleados en el desarrollo de aplicaciones Java y, ms concretamente, aplicaciones J2EE con interfaz HTML. La estandarizacin de juegos de caracteres surge ante la necesidad de intercambiar informacin de tipo carcter entre diferentes plataformas. En los orgenes de la informtica cada fabricante empleaba su propia codificacin de caracteres. Esto ocasionaba errores en el intercambio de informacin. Por ejemplo, IBM codificaba el carcter a como 033, mientras que para HP 033 era el carcter %. Cuando en un ordenador HP abramos un fichero de texto creado con un equipo de IBM, todas las letras a se vean como %. La estandarizacin del juego de caracteres implica dos decisiones: 1. Elegir el conjunto de caracteres (realmente smbolos) que formaran nuestro repertorio. Cuantos ms caracteres, ms bits necesitaremos para codificarlos. 2. Asignar una codificacin binaria nica para cada carcter. Algunos casos histricos importantes: EBCDIC Juego de caracteres empleado por mainframes de IBM. Tiene su origen en el cdigo de tarjetas perforadas de 1960. Algunas consolas te permiten especificar esta codificacin por lo que todava debe haber por ah sistemas que lo utilizan. ASCII 7bits Es el primer juego de caracteres de amplia difusin entre fabricantes. Incluye caracteres del alfabeto anglosajn, cifras, grficos y de control. ASCII 8bit Extiende el ASCII 7 con 128 nuevas posibilidades que se emplean para aadir caracteres de alfabetos y smbolos nacionales. Por ejemplo, los caracteres acentuados, diresis, la letra , etc. El ASCII en su versin 8 bits es adaptado en diferentes regiones para emplear los 128 bits superiores con smbolos locales. Cada adaptacin ha sido estandarizada por la ISO. Las ms relevantes para nosotros son: ISO 8859-1 (Latin-1).- Incluye los caracteres empleados por los pases de Europa Occidental. Est bien, pero no contiene el smbolo del Euro. ISO 8859-15 (Latin-9).- Revisin del anterior juego de caracteres para aadir el sbolo del Euro () y algunos caracteres del francs, fins y estonio que faltaban. En principio, parecera el idel para nosotros, pero no est ampliamente difundido. Por ejemplo, MySQL no lo incorpora. El ASCII 8 bits en sus diferentes estandarizaciones es soportado por la mayora de los navegadores. Eso si, hay que informar al navegador de que juego de caracteres est codificado el contenido de la pgina html para que pueda representarla de forma correcto. Esto se explicar posteriormente.

UNICODE ISO 10646 Es el estndar final y definitivo J. Originalmente fue diseado para emplear 16bits por carcter, pero posteriores ampliaciones lo han llevado a emplear el rango hexadecimal 0000000 a 0x10FFFF. Codifica los caracteres empleados por todas las lenguas vivas, algunas lenguas muertas, ideogramas, notaciones musicales, elementos de control, etc., etc., etc. El estndar evoluciona aadiendo nuevos caracteres a su repertorio. Es mantenido por el Unicote Tcnica Comit (UTC) donde estn representados los grandes jugadores de la industria informtica. Est ampliamente asimilado por la tecnologa actual: navegadores, lenguajes de programacin, sgbd, etc. El conjunto de smbolos soportado por unicote se divide, para facilitar su identificacin, en subconjuntos llamados planos, cada uno de un mximo de 65535 elementos (2Bytes). Plano Basico Multilingue (BPM) o Plano 0: Contiene la mayora de los alfabetos modernos y algunos ideogramas frecuentes. Plano Suplementario Multilingue (SPM) o Plano 1: Alfabetos Histricos de uso menor y smbolos tcnicos. Plano Suplementario Ideogrfico (SIP) o Plano 2: Ideogramas raros e histricos. Plano de Proposito Especial (SSP) o Plano 14: Caracteres de control. Plano de Uso Privado, Planos 15 y 16. Reservado para aplicaciones a medida. El gran problema de este estndar es el gran nmero de bits necesarios para codificar cada smbolo, 4Bytes. Para solucionar este problema se han definido tres formatos conocidos como UTF (Unicode Transformation Format) o UCS (Unicode Charset Set). UTF-8/UCS Codificacin de longitud variable. Representa los caracteres del ASCII7 con 8bits, los caracteres latinos especiales (,, etc.) con 16bits y, finalmente, otros caracteres con 24 y 32 bits. Para poder codificar los caracteres de forma variable emplea los bits ms significativos de cada Byte para identificar el nmero de Bytes del carcter que se representa y para identificar los diferentes Bytes que lo conforman (en caso de ms de 1Byte): Bytes 1 2 3 4

0xxxxxxx 110xxxxx 10xxxxxx 1110xxxx 10xxxxxx 10xxxxxx 11110xxxx 10xxxxxx 10xxxxxx 10xxxxxx

La consecuencia ms importante es que los caracteres ASCII 7 bits son compatibles con UTF-8, pero no las extensiones del ASCII 8 bits. Por ejemplo, si una pgina HTML codificada con UTF-8 transporta el carcter a y el navegador asume codificacin ISO -8859-1, la letra se visualizar correctamente porque su representacin en los dos juegos de caracteres es la misma. Sin embargo, si la pgina transporta una de cdigo 0XC3B1 el navegador la interpretar como los dos caracteres Latin-1 (0XC3 0xB1)=(). Este formato es el ms empleado. Algunos ejemplos: est reconocido por la Internet Task Force (IETF), ha sido elegido por el Internet Mail Consortium (IMC) para la comunicacin por correo electrnico, se emplea como codificacin por defecto en Linux y como representacin de caracteres en el COLLATE empleado por defecto de SQL Server 2005.

UTF-16/UCS-2.- Codificacin de longitud variable orientada a la representacin completa del plano Bsico Multilingue (BPM). UTF-32/UCS-4.- Codificacin de 32 bits de longitud fija. Codifica directamente el juego de caracteres Unicode. A estos juegos de caracteres se aaden, como siempre, las versiones realizadas por Microsoft de los mismos (con el objeto bsico de putear a la gente). El ms importante para nosotros es el CP1252/Windows-1252 que es ms o menos similar al Latin-1 y que es el juego de caracteres por defecto para Windows NT y posteriores (2000, XP, etc.) . Este juego de caracteres tiene la peculiaridad de contener el smbolo del euro (por eso podemos escribirlo en Windows) y de codificarlo con la misma representacin que le da la ISO-8859-15. JUEGO DE CARACTERES EN INTERFACES HTML La mayora de los navegadores (Opera, Firefox, MS Explorer) pueden representar sin problemas paginas html en diferentes juegos de caracteres. En este sentido no hay un problema tecnolgico. Para poder mostrar los textos correctamente hay que informar al navegador del juego de caracteres con el que se transmite el contenido HTML a visualizar. De lo contrario, el navegador tomar un criterio por defecto (que debera ser UTF-8 *** buscar la referencia ****) y si no coincide con la codificacin de la pgina los caracteres no se vern correctamente. Nota.- El navegador, cuando hace una peticin GET informa de los juegos de caracteres que soporta con la cabecera: Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 El servidor web comunica al navegador el juego de caracteres de la respuesta HTTP mediante la cabecera: Content-Type: text/html;charset=utf-8 Esta cabecera puede generarse de muchas formas, aunque las ms habituales son: Para pginas HTML. Aadir el tag:
<META HTTP-EQUIV="content-type" CONTENT="text/html; charset=utf-8">

Para JSPs. Aadir el tag:


<%@ page contentType="text/html; charset=utf-8"%>

Aunque la versin ms frecuente de la anterior directiva es la versin completa siguiente:


<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="charset=UTF-8"%>

La propiedad pageEncoding indica al compilador de jsps que el fichero JSP, en s mismo, est codificado con UTF-8. De esta forma la directiva permite diferenciar entre la codificacin empleada para trabajar, programar los jsps, y la codificacin con la que se transmite el resultado html al cliente. Algunos IDES, como eclipse o bea workshop detectan esta propiedad y fuerzan que la codificacin real del archivo jsp y la declarada coincidan. Algunos contenedores J2EE como Weblogic o Sun One disponen de una propiedad que permite configurar el juego de caracteres empleado en las respuestas a nivel de WebApp lo que evita que se

tenga que poner la anterior cabecera en todos los JSPs. En weblogic se configura con el descriptor especfico del contenedor weblogic.xml:
<jsp-descriptor> <jsp-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </jsp-param> </jsp-descriptor>

Curiosidad: Firefox y Explorer interpretan el cdigo 80H de un mensaje ISO-8859-1 como el smbolo del Euro () a pesar de que dicho smbolo no est en ese juego de caracteres. La razn es que los cdigos del 80H al 9FH del ISO-8859-1 estn sin utilizar, mientras que el cdigo 80H corresponde al Euro en Windows-1252, codificacin por defecto en las localizaciones de Windows para Europa occidental y America. Por esto, los dos navegadores, muy convenientemente, interpretan que si en una pgina ISO-8859-1 les llega un cdigo 80H, muy probablemente se trate del smbolo del euro y as lo dibujan. Hasta aqu todo bien. Es decir, podemos enviar contenidos html a un navegador web empleando el juego de caracteres que ms nos convenga sin mayor problema que el juego sea soportado por el navegador. La transmisin en sentido contrario es ms complicada. Con qu juego de caracteres se transmiten los datos que un usuario introduce en un formulario HTML? El navegador, por defecto, intentar devolver el contenido de los formularios en el mismo juego de caracteres asignado a la pgina (por indicacin explcita de la cabecera HTTP o por defecto). Este criterio se aplica tanto si el mtodo elegido es GET como POST. En el caso especial de GET, si alguno de los caracteres introducido por el usuario no tiene representacin en el juego de la pgina, se enviar con notacin numrica (Numeric Character Referente NCR ej.- &#931). Una forma de forzar que los caracteres del formulario empleen una codificacin especfica es la propiedad accept-charset de los Form. El siguiente formulario enviar su contenido en utf-8 independientemente del juego de caracteres empleado para representar la pgina que lo contiene:
<form action=nuevoCliente method=POST accept-charset=utf-8>

Evidentemente, esto no ser muy frecuente, supone un engorro en el desarrollo de los formularios y es poco flexible, por lo que parece razonable basar los desarrollos en que la codificacin devuelta por el navegador es la misma de la pgina. Bueno, independientemente del medio empleado por el navegador para decidir la forma de codificar la informacin transmitida, el problema lo tenemos en que el servidor que recibe esta informacin NO TIENE FORMA DE DETERMINAR LA CODIFICACION EMPLEADA. Hay que tener en cuenta que http es un protocolo sin estado y que el servidor web no recuerda el juego de caracteres con el que envi la pgina web que contiene del formulario. Tericamente, el estndar http permite especificar la codificacin empleada en los contenidos de tipo multipart-form-data, de la misma forma que se hace con la los contenidos text/html, pero en la prctica, los navegadores no insertan esta informacin. Buscando por Internet, incluso he encontrado casos de navegadores que lo hacen (alguna versin para dispositivos mviles) y este comportamiento ocasiona errores en los servidores web.

Para solucionar este problema algunos contenedores como weblogic y Sun One disponen de opciones de configuracin en sus descriptores especficos que permiten indicar la codificacin que debe suponer el servidor a la hora de procesar las respuestas del navegador.
Weblogic.xml <charset-params> <input-charset> <resource-path>/*</resource-path> <java-charset-name>UTF-8</java-charset-name> </input-charset> </charset-params> Sun-web.xml <parameter-encoding default-charset="UTF-8"/>

Tomcat permite especificar URLEncoding en un conector pero, como su nombre indica, solo afecta a los parmetros que se reciben por get (en la URL). La mejor solucin en Tomcat es aadir un filtro que proporcione informacin al resto de la pila de procesamiento de la peticin http sobre la codificacin que se espera enve el navegador.
public class CharsetFilter implements Filter { private String encoding; public void init(FilterConfig config) throws ServletException { encoding = config.getInitParameter("requestEncoding"); if( encoding==null ) encoding="UTF-8"; } public void doFilter(ServletRequest request, ServletResponse response, FilterChain next) throws IOException, ServletException { if(null == request.getCharacterEncoding()) request.setCharacterEncoding(encoding); next.doFilter(request, response); } public void destroy(){} }

Este filtro fija en el objeto request el CharacterEncoding en caso de que no lo haya hecho el navegador. No hace nada ms. Hay que entender que no procesa de ninguna forma el contenido del request, solo lo etiqueta para que la implementacin de getParameter(String):String sepa como decodificarlo. El servlet debe situarse el primero de la pila de filtros. Para ello, debe ser el primero objeto de una directiva <filter-mapping> (el orden de declaracin del filtro es indiferente para su orden de aplicacin de los filtros).
<filter> <filter-name>Charset Filter</filter-name> <filter-class>CharsetFilter</filter-class> <init-param> <param-name>requestEncoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>Charset Filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>

JUEGOS DE CARACTERES Y BBDDS Partimos de la base de que las conexiones a BBDDs las hacemos mediante drivers JDBC. Tenemos entonces, por un lado caracteres representados en el formato interno de la mquina virtual java (utf-16) y por otro el empleado por la bbdds, que puede especificarse a nivel de servidor, bbdds, tabla o, incluso, campo (al menos en mysql se permite este nivel de refinamiento). Uno podra esperar, de forma ms o menos razonable, que el driver detectara el encoding empleado en el extremo de la BBDDs y asumiera la responsabilidad de la transformacin. No siempre es as. La documentacin del driver de MySQL indica que detecta el encoding de la BBDDs pero en las pruebas que he realizado no es as. Tienes que basarte en propiedades especficas del driver para configurar correctamente la conversin de caracteres. En cualquier caso, aunque resolviramos la forma de transformar correctamente los caracteres unicode de java al juego de la BBDDs siempre nos vamos a encontrar con el problema de que usemos caracteres (como el smbolo del euro) que no tengan representacin en el juego por defecto de la BBDDs (Latin-1 en el caso de Mysql). Por todo ello, la mejor opcin es trabajar siempre con almacenamiento en BBDDs en Unicode. MySQL por defecto emplea latin-1, pero puede especificarse el uso de utf-8 a nivel de servidor, bbdds, tabla o campo. Parece que el nivel de BBDDs es el ms adecuado. Puede crearse una BBDD con un utf8 como encoding por defecto mediante la instruccin: Create database pruebas default charset utf8 default collate utf8_general_ci; El collate de la BBDDs registra el criterio de ordenacin alfabtico y las igualdades entre caracteres. Por ejemplo, en el anterior collate los caracteres: u, U, , , , etc son iguales en lo que respecta a una comparacin entre cadenas. El collate especificado en la instruccin anterior utf8_general_ci es el por defecto para el utf8 en MySQL, por lo que no es necesario especificarlo. En la direccin http://www.collation-charts.org/ se pueden consular algunos collations empleados por bbdds, navegadores, etc. Los clientes grficos que acompaan a MySQL se conectan suponiendo codificacin por defecto. Es necesario configurar adecuadamente la conexin para poder ver los caracteres en utf. Igualmente, si te conectas con un terminal remoto como putty y empleas el cliente mysql en una consola de texto, tendrs que configurar tanto mysql con la opcin default-character-set=utf8 como putty indicando el juego de caracteres de la consola. JUEGOS DE CARACTERES EN LOS SISTEMAS OPERATIVOS Cada sistema operativo puede emplear un juego de caracteres por defecto para representar sus archivos. Algunos ejemplos: Linux: UTF-8 Windows XP: Cp1252

En el caso de Windows, la configuracin puede variar dependiendo del Locale de la instalacin del sistema operativo. JUEGOS DE CARACTERES EN JAVA Java representa internamente los caracteres correspondientes a datos de programa en su codificacin UNICODE UTF-16 (16 bits por carcter, igual que un entero). Los caracteres que corresponden a representaciones de smbolos propios del lenguaje, como pueden ser identificadores, palabras reservadas, etc. los representa en ASCII 7 bits (por definicin del lenguaje no pueden tener caracteres multibyte). Para comunicarse con el exterior por medio de ficheros (lectura o escritura) o conexiones de red, los caracteres se transforman a una codificacin determinada que est determinada por al propiedad file.enconding (System.getProperty( file.encoding );). El valor de esta propiedad suele tomar por defecto el mismo valor de la codificacin empleada por el sistema operativo donde se instala la jvm. Por ejemplo, en mi Windows XP es Cp1252. Puede modificarse al lanzar la mquina virtual. Por ejemplo:
-Dfile.enconding=utf-8

La configuracin de file.enconding afecta tambin a los ficheros de cdigo fuente que son compilados con javac. Los Reader y Write se encargan de realizar las conversiones automticamente entre codificaciones de caracteres. Si se quiere forzar una conversin se puede emplear:
String miCadena=Prueba de can; Byte[] codificado=miCadena.getBytes(8859_1);

Algunos desarrolladores defienden que la mejor forma de evitar problemas es trabajar siempre en UTF-8. No obstante, otros advierten que esta codificacin presenta comportamientos inesperados en MS Internet Explorer. JUEGOS DE CARACTERES EN ECLIPSE Eclipse, por defecto, crea ficheros nuevos con el juego de caracteres definido por el file.enconding de la maquina virtual sobre la que corre. Esto significa que en Windows es Cp1252. Los archivos creados fuera de eclipse se editan con el juego de caracteres con el que vinieran. Ambos comportamientos pueden modificarse en las preferencias: Preferentes -> General -> Workspace ->Text file Encoding CONCLUSIONES La mejor forma de no complicarse es emplear siempre un mismo juego de caracteres en todos los niveles tecnolgicos de la solucin. Para ello, hay que elegir un encoding que sea lo suficientemente completo como para cubrir todos los caracteres que empleamos habitualmente y estandarizado como para poder sea soportado por todas nuestras herramientas tecnolgicas: documentacin, ides, bbdds, etc. En este sentido, la mejor opcin es emplear utf-8 como juego de caracteres por defecto en todos nuestros desarrollos.

Es cierto que hay herramientas que precisan ajustes para emplearlo. Pero ya est lo suficientemente extendido su uso como para que este factor no parezca un riesto significativo. REFERENCIAS 1. 2. 3. 4. 5. 6. 7. 8. 9. Character conversion. Faq de internacionalizacin de JAVA. Encoding y Java Java SE Specifications Tomcat Wiki Codificacin de caracteres de Java Character Enconding and HTML Forms UTF-8: The Secret of Character Encoding MySQL Character Set Support

También podría gustarte