Cadenas de caracteres Unicode en Delphi (Parte I)

Justificación

Mi motivación para escribir este, y otros artículos sobre características no tan nuevas de Delphi, es que muchos programadores de habla hispana hoy día siguen sin conocer algunos o muchos de los detalles sobre las mismas.  En este caso particular, desde la versión 2009 las cadenas de caracteres son Unicode, pero muchos enfrentan problemas relacionados con el tratamiento de archivos o la comunicación con otros sistemas, incluyendo los motores de bases de datos, en parte debido a la poca información que hay disponible en Español sobre el tema. Este es el primero de una serie de artículos sobre Unicode en Delphi.

A estas alturas seguramente sabes o al menos has escuchado que Delphi es Unicode y probablemente lo usas en tu día a día, en cualquier versión igual o superior a la 2009.  Por lo mismo, no iremos por todos los detalles, pues como ya has podido comprobar, Unicode es fácil de usar y la mayor parte del tiempo puedes trabajar con él y sacarle provecho aún sin conocer sus detalles.  La intención de la serie de artículos tampoco es darte un conocimiento profundo sobre Unicode en si, pues hay mucha información sobre el estándar en la red, sino más bien darte un mayor grado de comprensión sobre cómo Delphi enfrenta el tema, cómo migrar aplicaciones realizadas en versiones anteriores de la herramienta y cómo puedes inter-operar con otros sistemas que no son Unicode o que requieren el uso de alguna representación específica de la información textual.  Estés o no ya trabajando con Unicode, espero que encuentres alguna información que te sea de utilidad.

Delphi Unicode

Ideograma chino Yue (luna)
Ideograma chino Yue (luna) (U+6708)

En Delphi 2009 o superior, al declarar una variable de tipo Char, PChar o string, estamos declarando contenedores que tienen soporte para el conjunto de caracteres Unicode, y por tanto pueden representar información textual de cualquier alfabeto soportado por el estándar, como japonés, chino, árabe, cirílico, sin olvidar las lenguas latinas como el español, portugués, francés, italiano y y otras.

El primer beneficio directo de esto, es que los caracteres que no pertenecen al alfabeto inglés, como las vocales con tilde o la eñe del español, tienen una única representación en el conjunto de caracteres y no dependen ya de la configuración local de Windows, como era el caso de cadenas ANSI. ¿A quién no le ha ocurrido que una aplicación almacena información textual que de pronto se corrompe, puesto que lo que antes era «Atlántico» de pronto se convierte en «Atl?ntico»?  Empecemos pues por el principio.

¿Qué es Unicode?

Unicode es el nombre de un conjunto internacional de caracteres, que abarca los símbolos de todos los alfabetos de escritura conocidos, además de símbolos técnicos, de puntuación y otros caracteres utilizados para la escritura, aún cuando no forman parte de ningún alfabeto. El estándar Unicode, formalmente conocido como ISO/IEC 10646, ha sido definido y documentado por el consorcio Unicode.

Unicode en esencia es muy simple, pues especifica un único identificador numérico, llamado code point, para cada símbolo.

Representación en memoria

Dada la gran cantidad de símbolos existentes en el estándar (más de 100,000) hay varias maneras de representar un mismo code point en memoria. La única manera de representar todos los caracteres de manera simple y uniforme, es usando cuatro bytes (32 bits) para cada caracter, sin embargo esto resulta costoso en términos de memoria y proceso.

Composición ñ
Composición de la letra ñ

Unicode Transformation Format, abreviado como UTF, es parte del estándar y asigna a cada code point una secuencia única de bytes que lo representan, en tres formatos distintos. Las asignaciones funcionan en ambas direcciones y sirven para convertir entre las diferentes representaciones existentes, que son:

  • UTF-8, codificación de largo variable entre 1 y 4 bytes;
  • UTF-16 es también una codificación de largo variable que usa 2 o 4 bytes para representar cada code point
  • UTF-32 representa todos los caracteres usando siempre 4 bytes.

Entre las representaciones UTF-16 y UTF-32 se soporta tanto la forma big-endian como little-endian, dependiendo del orden en que se colocan los bytes. Cuando se almacena un archivo de texto Unicode, se puede grabar una cabecera con una firma indicando explicitamente la representación contenida.

Firma Forma
00 00 FE FF UTF-32, big-endian
 FF FE 00 00 UTF-32, little-endian
 FE FF UTF-16, big-endian
 FF FE UTF-16, little-endian
 EF BB BF UTF-8

Delphi actualmente utiliza la representación UTF-16 little-endian para toda variable string, Char o PChar declarada.

PRÓXIMAMENTE

En una próxima entrega hablaremos en más detalle sobre los tipos de variables que se pueden declarar y la forma de hacer conversiones entre strings ANSI (ASCII) y Unicode, así como de resolver algunas advertencias del compilador al migrar aplicaciones hechas con versiones anteriores de Delphi.  Si deseas ser notificado por correo cuando se publiquen las siguientes entradas, no olvides suscribirte al blog.

Atribuciones

Las imágenes utilizadas en esta entrada son de la autoría de Magna (Yue) y Marco Regueira (composición ñ)