Search

Search this site:

Codificación de Caracteres

NOTA: Al preparar este texto, excedí el límite de espacio que me asignan, por lo cual después de terminar de escribir tuve que ver qué párrafos eran más prescindibles. Acá reproduzco el artículo completo, y adjunto como archivo la versión tal cual apareció impresa.
<p>Hace un par de días recibí uno de esos correos que parecen venir de una época ya superada y olvidada hace años: Un correo que comenzaba con la frase:</p>

<blockquote>Para evitar problemas de compatibilidad, este correo no incluye acentos ni enies</blockquote>

<p>En efecto, este problema casi ha desaparecido del correo, y ese pretexto sencillamente ya no resulta ni siquiera una excusa adecuada para quien le da flojera escribir el español correctamente.</p>

<p>Sin embargo, no en todos los campos podemos hablar de un éxito tan grande como en el manejo del correo electrónico — Y es de esperarse. La naturaleza misma del correo lo requiere. Cada mensaje individual debe ser transportado, sin que le sean inflingidas modificaciones por agentes externos, entre los equipos de los participantes en una conversación — que pueden estar configuradas con referentes culturales completamente distintos.</p>

<p>Y si bien para los hispanoparlantes, especialmente para aquellos que sienten que el uso de <em>símbolos internacionales</em> (acentos, tildes y signos de apertura de interrogación/exclamación) es opcional, el correo funcionó <em>casi bien</em> desde un principio (y a continuación detallaremos el por qué), cuando el uso de Internet dio su gran salto cuantitativo en los 1990s y llegó a la población en general, para los nativos de muchas otras culturas alrededor del mundo se hizo imperativo encontrar cómo comunicarse confiablemente.</p>

<p>Pero el problema viene de mucho más atrás. Repasemos rápidamente la historia de los esquemas de codificación de caracteres.</p>

<h3>Repaso histórico</h3>

<p>La codificación a partir de la cual se originan todos los esquemas en uso hoy en día nació en 1963, revisado/ratificado en 1967 con el nombre de ASCII: <em>Código Estándar Americano para el Intercambio de Información</em>. ASCII es un código de 7 bits, permitiendo la representación de hasta 128 caracteres, y en su versión definitiva incluye 32 caracteres de control, 34 símbolos, 52 caracteres de texto (mayúsculas y minúsculas) y 10 dígitos.</p>

<p>Sobra decir que el ámbito cómputo ha cambiado drásticamente desde 1963. La computadora debía representar apenas la información indispensable para ser comprendida por sus   operadores, y en la propuesta original, ASCII no incluía ni   siquiera letras minúsculas <span class="ref"(Jennings   1999-2004)</span>. Pero ya en 1964 aparecieron las máquinas de   escribir IBM MT/ST: Una máquina de escribir electrónica, con la   capacidad de guardar (y corregir) páginas en cinta   magnética. Fue sólo cuestión de tiempo (y del necesario paso de   popularización que siguió a la revolución de las computadoras   personales hacia fines de los 1970) para que estas capacidades quedaran al alcance de todo mundo.</p>

Y es ahí donde se hizo obvio que haría falta extender ASCII: Todos los idiomas europeos que utilizan el alfabeto latino a excepción del inglés requieren de diferentes tipos de diacríticos para ser representados; tras varias ideas descartadas, se aprovechó el hecho de que hacia fines de los 1970 todas las computadoras ampliamente desplegadas tenían un tamaño de palabra de 8 bits para utilizar un ASCII ampliado que daría 128 caracteres adicionales. Sin embargo, la idea resonó rápidamente… Y no surgió un estándar para su uso. Además, muchos de estos caracteres fueron empleados para incluir caracteres gráficos, para permitir construir interfaces amigables al usuario.

En 1981, IBM puso a la venta su primer computadora personal - La IBM 5051, o como se popularizó, la PC. Entre sus características contaba con una tarjeta de video con páginas de códigos reprogramables — La mitad superior del espacio de caracteres podía ser definida por software; los caracteres cargados por omisión eran los de la página de códigos 437 (CP437), con soporte parcial para algunos lenguajes europeos, pero –debido al espacio empleado por los caracteres semigráficos para representar interfaces al usuario– nunca fueron suficientes, por lo que en general era necesario activar una página de código alternativa — Para el español, la CP850. La situación mejoró al popularizarse los entornos gráficos y dejar de depender de los caracteres semigráficos; varias hojas de código relacionadas pudieron agruparse en un menor número — En este caso, para lenguajes europeos occindentales, la ISO-8859-1.

El problema se presenta al intercambiar archivos con usuarios de otras páginas: Los datos que usan una página son indistinguibles que los que usan otra. Si compartiera un archivo ISO-8859-1 con una persona de Europa oriental (ISO-8859-2), los caracteres acentuados aparecerían modificados, aparentemente corruptos. La situación de los lenguajes de Asia oriental era mucho peor aún, dado que por la cantidad de glifos, plantear el uso de un alfabeto de 256 caracteres resultó imposible — y por muchos años, la interoperabilidad fue meramente un sueño.

En 1988, Joe Becker, Lee Collins y Mark Davis, de Xerox y Apple, se reunieron para atacar este problema de raiz: Lanzaron la iniciativa del sistema Unicode, buscando aprovechar los grandes avances de más de 20 años del cómputo para lograr un conjunto de caracteres apto para todo el mundo. Pronto su iniciativa logró captar la atención y el respaldo de otros líderes del desarrollo del cómputo.

El desarrollo de Unicode no está libre de desaciertos y peleas políticas, pero el resultado bien lo valió: Para 1996 se publicó la especificación Unicode 2.0, permitiendo un espacio de más de un millón (216+220) de puntos de código independientes, reteniendo compatibilidad hacia atrás completa con el principal esquema heredado (ISO-8859-1), derivado de CP850.

Unicode es tan grande que su representación interna no está libre de polémica e interpretaciones. Sin entrar en detalles técnicos, las dos principales representaciones son UTF-8 (utilizada en sistemas basados en Unix, y en general, para toda transmisión sobre redes de datos) y UTF-16, descendiente de UCS-2 (en uso principalmente en sistemas Windows).

No entraré mucho en detalles respecto a estas dos representaciones — Es sólo importante estar conscientes de que una cadena Unicode puede estar representada internamente de diferentes maneras; UTF-8 está basado en elementos individuales de 8 bits, mientras que el átomo en UTF-16 es de 16 bits, por lo que –especialmente con idiomas basados en el alfabeto latino– UTF-8 es más compacto (con UTF-16, el byte superior consistirá sólamente de ceros) y es sensiblemente más robusto para transmisiones sobre la red (una corrupción de datos afecta un punto mínimo, mientras que con UTF-16 puede hacer ilegible todo el texto a partir de ese punto).

Un punto importante a mantener en cuenta es que la representación binaria de texto ASCII heredado es idéntica a su representación en UTF-8 — No así con UTF-16. Para más detalles respecto a estas dos representaciones, así como las otras varias posibles, sugiero leer (Wikipedia Comparación).

¿Qué hace diferente al tratamiento de Unicode?

Hasta antes de Unicode, todo lo que teníamos que saber respecto a un esquema de codificación se limitaba a elegir la salida adecuada, o interpretar la entrada como debía ser. Y Unicode agrega muchos puntos a la mezcla. algunos de ellos:

<dl>
  <dt>Longitud de una cadena</dt>
Como programadores, estamos acostumbrados a que la longitud caracteres de una cadena es igual a su tamaño entes. Unicode rompe con este supuesto — Para medir langitud ahora tenemos que evaluar la cadena completa ycontrar cuáles partículas son de qué tamaño — Un caracterede medir entre uno y seis bytes, y hay además caracteresm>combinantes</em>, que no ocupan un espacio por sí sólosno que modifican al anterior.
  <dt>No todas las cadenas son válidas</dt>
Con los esquemas tradicionales de 8 bits, todo conjunto deracteres es válido. Al hablar de las representaciones deicode, hay cadenas que resultan inválidas.
Si han visto una página Web donde los caracteres con diacríticos aparecen substituídos por caracteres en forma de rombo con un signo de interrogación dentro (, punto de código U+FFFD), éste caracter denota que el procesamiento de Unicode no pudo completarse. Sin embargo, no todas las aplicaciones son tan benignas como un navegador — Una base de datos, por ejemplo, debe negarse a guardar datos mal-formados, por lo cual debemos estar conscientes del tipo de excepciones que posiblemente recibiremos si nuestro usuario nos da datos inválidos.
  <dt>Caracteres definidos semánticamente, no visualmente</dt>
  <dd>Los caracteres en Unicode no buscan únicamente representar un grupo de grafías, sino que su significado. En tiempos del ASCII nos acostumbramos a utilizar la <em>representación gráfica</em> más cercana a un caracter. Por ejemplo, nos acostumbramos a representar a la multiplicación con el asterisco ya sea con la letra «x» o con el asterisco; con Unicode podemos usar –cual debe ser– el símbolo <span class="uchar">✕</span> (U+2715). Los alemanes ya 	no se ven forzados a usar la <span class="uchar">β</span> (beta griega, U+0392) en vez de la <span class="uchar">ß</span> (<em>Eszett</em> o <em>S fuerte</em>, U+00DF).<br/> Si bien esto es más una ventaja que nada, puede llevarnos a confusiones. Por ejemplo, si bien en ASCII con CodePage 850 sólo podemos representar a una letra acentuada de una manera (la letra <span class="uchar">á</span> está en la posición 160), en Unicode puede representarse en este mismo punto, o como la combinación de una a minúscula (caracter 95, U+0061) y un caracter combinante de acento agudo (U+0300): <span class="uchar">á</span>. Esto permite la gran expresividad que requieren algunos idiomas o alfabetos (ver <span class="ref">(Wood 1999-2009)</span> con una clara ejemplificación de la expresividad que otorgan), pero nos obliga a considerar más casos especiales al enfrentarnos a Unicode desde el punto de vista del desarrollador de sistemas.</dd>
</dl>

<h3>Promesas, promesas…</h3>

<p>Como ya lo hemos discutido en este mismo espacio, el punto que     más debemos cuidar como desarrolladores son los puntos de cruce      — Las barreras, las <em>costuras</em> en la realidad. Lo ideal      sería que no hiciera falta que un componente le dijera      explícitamente al otro que está listo y dispuesto para usar      Unicode. Un sistema operativo instalado limpiamente el día de      hoy, así como casi cualquier aplicación que instalemos sobre de       éste, debe funcionar bien –y de manera predeterminada– con       Unicode. Claro está, la realidad siempre se interpone — Por un       lado, podemos tener que interactuar con       componentes <em>heredados</em>. Por otro lado, no podemos       olvidar el hecho de que muy rara vez podemos controlar el       entorno de nuestros usuarios — Y por último, un punto donde nos       toparemos ineludiblemente con problemas de codificación es al       hablar con dispositivos externos.</p>

<p>Si bien es posible aplicar reglas heurísticas para determinar       si una cadena es válida o no como UTF-8 <span class="ref">(Dürst       1997)</span>, prácticamente cualquier protocolo que utilicemos       hoy en día para transmitir contenido que deba ser interpretado       como texto proporciona un campo en su encabezado para indicar el       tipo de contenido a utilizar — Sin olvidar tomar en cuenta que       muchos protocolos contemplan la transmisión de       datos <em>multipartes</em>, ¡y cada una de las partes puede       llevar codificaciones diferentes!</p>

<h3>Conclusiones</h3>

<p>Viendo sólamente estos puntos, puede que muchos de ustedes los       vayan poniendo en la balanza, y les parezca que migrar a Unicode       es demasiado dificil y no vale la pena. Sin embargo,       sencillamente, no nos queda opción: El mundo entero va avanzando       en ese sentido. </p>

<p>Si bien nos toca la parte más simple, por ser nativos de una       cultura basada en el alfabeto dominante en Internet, no podemos       ignorar que formamos parte de un mundo plenamente globalizado, y       que los días de vivir en nuestra islita feliz de un sólo       alfabeto han terminado.</p>

<p>Del mismo modo que sencillamente ya no es aceptable que una       aplicación falle cuando le enviamos datos escritos correctamente       acentuados, tampoco es aceptable que rechacemos registrar a       personas cuyo nombre tiene origen extranjero, o que tienen una       dirección de destinatario no representable con caracteres       latinos. Ni es aceptable, en un mundo que tiende a la       presentación de software como servicio «en la nube», no ofrecer       una solución capaz de manejar los datos enviados por usuarios de       todo el mundo es ofrecer una solución con baja calidad de       servicio.</p>

<h3>Referencias</h3>

<ul>
  <li><span class="ref">(Jennings 1999-2004)</span> Annotated history of character codes http://wps.com/projects/codes/index.html</li>
  <li><span class="ref">(Dürst 1997)</span> The Properties and Promizes of UTF-8 http://www.ifi.unizh.ch/mml/mduerst/papers/PDF/IUC11-UTF-8.pdf</li>
  <li><span class="ref">(Czyborra 1995-2000)</span> Unicode in the Unix Environment http://www.unicodecharacter.com/</li>
  <li><span class="ref">(Wood 1999-2009)</span> Combining Diacritical Marks http://www.alanwood.net/unicode/combining_diacritical_marks.html</li>
  <li><span class="ref">(Wikipedia Comparación)</span> Comparison of Unicode encodings http://en.wikipedia.org/wiki/Comparison_of_Unicode_encodings</li>
</ul>

Attachments

Versión del artículo publicada en la revista (1330 KB)