Saltar a contenido

Textos

Un texto es una secuencia de caracteres, donde cada letra del alfabeto tiene asignado un código numérico. Ya hemos visto como ejemplo la palabra “Hola”, que es una secuencia de cuatro caracteres:

Byte Carácter Código En binario En hexadecimal
1º byte H 72 0100 1000 48
2º byte o 111 0110 1111 6F
3º byte l 108 0110 1100 6C
4º byte a 97 0110 0001 61

Por lo tanto, esta palabra se almacenará en la memoria RAM haciendo uso de cuatro bytes, y mediante la siguiente secuencia de bits:

0100 1000 0110 1111 0110 1100 0110 0001

o lo que es lo mismo, en hexadecimal:

48 6F 6C 61

Dentro de un texto podemos incluir dígitos numéricos, que serán considerados como caracteres regulares:

Carácter Código En binario En hexadecimal
0 48 0011 0000 30
1 49 0011 0001 31
2 50 0011 0010 32
3 51 0011 0011 33
4 52 0011 0100 34
5 53 0011 0101 35
6 54 0011 0110 36
7 55 0011 0111 37
8 56 0011 1000 38
9 57 0011 1001 39

Las mayúsculas y minúsculas son caracteres diferentes:

Carácter Código En binario En hexadecimal
A 65 0100 0001 41
a 97 0110 0001 61

El espacio en blanco es un carácter más, representado con un código 32 en decimal, 20 en hexadecimal y 0010 0000 en binario.

Los símbolos de puntuación son caracteres:

Carácter Código En binario En hexadecimal
! 33 0010 0001 21
" 34 0010 0010 22
# 35 0010 0011 23
$ 36 0010 0100 24
% 37 0010 0101 25
& 38 0010 0110 26
' 39 0010 0111 27
( 40 0010 1000 28
) 41 0010 1001 29
* 42 0010 1010 2A
+ 43 0010 1011 2B
, 44 0010 1100 2C
- 45 0010 1101 2D
. 46 0010 1110 2E
/ 47 0010 1111 2F

Existe un caso especial de caracteres denominados “de control”. Cuando enviamos texto a una impresora, por ejemplo, lo que transmitimos es una secuencia de códigos. Un código 10 representa un salto de línea, un 9 es un tabulador, un 12 sirve para saltar a la página siguiente, y así sucesivamente.

Codificaciones

¿Quien determina el código asignado a cada letra del alfabeto? En los inicios de la informática, cada fabricante de ordenadores tenía su propia codificación, pero cuando surgió la necesidad de transmitir datos de una máquina a otra, hubo que llegar a un acuerdo y establecer codificaciones estándar.

Históricamente la codificación más popular ha sido ASCII, abreviatura de Código Estándar Americano para Intercambio de Información. Véase una lista de los códigos asignados a cada carácter en la Wikipedia. Los ejemplos vistos en el apartado anterior siguen ese estándar.

ASCII presenta un problema importante: solo recoge los caracteres del alfabeto inglés, así como los dígitos numéricos y los símbolos de puntuación, como es el caso de las comillas, paréntesis, punto y coma, etcétera. Pero no se incluyen caracteres como la ñ española, las francesas æ y œ, o la alemana ß, por ejemplo. Tampoco admite vocales acentuadas.

Para solucionarlo surgieron distintas versiones de ASCII ampliadas. Una de las más populares fue la ISO 8859-1, que añade caracteres de la Europa occidental. Esta codificación también es conocida como Latin-1.

Tanto ASCII como Latin-1 utilizan un byte para cada carácter, quedando limitado a un juego máximo de 256 caracteres, es decir, el número de combinaciones que tenemos con 8 bits. Sin embargo esto es claramente insuficiente para representar idiomas fuera del ámbito europeo.

Fruto de esta inquietud, en la década de 1980 surgió un grupo de trabajo impulsado por Xerox y Apple, para elaborar una propuesta de caracteres de 16 bits, lo que proporciona una capacidad de 65.536 combinaciones diferentes. Finalmente se creó el consorcio UNICODE, integrado actualmente por importantes empresas como Adobe, Apple, Facebook, Google, IBM o Microsoft, por ejemplo. A lo largo de los años se han ido desarrollando tres codificaciones principales que llegan a utilizar hasta 32 bits por carácter, representando más de cien mil caracteres. Incluye todos los idiomas del mundo, símbolos matemáticos, técnicos, musicales, iconos, emojis, y un largo etcétera. Periódicamente se van incluyendo nuevas versiones con caracteres añadidos.

Las tres codificaciones de Unicode son:

  • UTF-8. Cada carácter puede ocupar uno, dos, tres o cuatro bytes, según el caso. Los caracteres del alfabeto anglosajón ocupan un byte y coinciden con la codificación ASCII.

  • UTF-16. Cada carácter se representa con 16 bits. El conjunto de caracteres que se pueden representar así se denomina “plano básico multilingüe”. Los caracteres extra que no forman parte de este conjunto, requieren 32 bits cada uno.

  • UTF-32. Es la codificación más simple, ya que todos los caracteres ocupan 32 bits.

Veamos algunos ejemplos.

La letra A mayúscula se representa de la siguiente forma:

  • ASCII: 01000001, en hexadecimal, 41 (un byte)
  • Latin-1: 01000001, en hexadecimal, 41 (un byte). Coincide con ASCII.
  • UTF-8: 01000001, en hexadecimal, 41 (un byte). Coincide con ASCII.
  • UTF-16: 00000000 01000001, en hexadecimal, 00 41 (dos bytes).
  • UTF-32: 00000000 00000000 00000000 01000001, en hexadecimal, 00 00 00 41 (cuatro bytes).

UTF 16 y UTF 32 tienen dos variantes cada una. En los ejemplos hemos usado UTF-16BE y UTF32BE respectivamente, pero tenemos las variantes UTF-16LE y UTF32LE, que consisten en poner los bytes al revés:

  • UTF-16BE: 00 41 (16 bits)
  • UTF-32BE: 00 00 00 41 (32 bits)
  • UTF-16LE: 41 00 (16 bits)
  • UTF-32LE: 41 00 00 00 (32 bits)

Los caracteres que no forman parte del juego ASCII, requieren más bytes en el caso de estándares Unicode. Por ejemplo:

  • Letra Ñ en UTF-8: C3 91, en binario, 11000011 10010001 (16 bits)
  • Letra Ñ en UTF-16: 00 D1, en binario, 00000000 11010001 (16 bits)
  • Letra Ñ en UTF-32: 00 00 00 D1 (32 bits)
  • Letra Ñ en latin-1: D1 (8 bits)

Símbolos matemáticos: infinito

  • UTF-8: E2 88 9E en hexadecimal (tres bytes)
  • UTF-16: 22 1E (dos bytes)
  • UTF-32: 00 00 22 1E (cuatro bytes)

Emojis: 😀

  • UTF-8: F0 9F 98 80 (cuatro bytes)
  • UTF-16: D8 3D DE 00 (cuatro bytes)
  • UTF-32: 00 01 F6 00 (cuatro bytes)

Véase que la codificación más simple y con más capacidad es la UTF-32. Sin embargo, también es la que supone mayor gasto de memoria, en términos de número de bits utilizados. UTF-8 es aparentemente la más compleja, por utilizar un número variable de bytes dependiendo del carácter, pero es una codificación muy popular, dado que es la que menos gasto supone y que, en el caso de limitarnos al alfabeto anglosajón, es totalmente compatible con ASCII.

¿Como podemos averiguar el código correspondiente a cada carácter? En Internet existen multitud de páginas de consulta. Basta con introducir el término de búsqueda “tabla de caracteres unicode”.

Siendo UTF-8 la más popular, ¿como funciona? Supongamos un texto formado por una secuencia de bytes cuyo primer byte es C3, en hexadecimal. ¿Es un carácter por si mismo o forma parte de una secuencia de dos, tres o cuatro bytes? Lo que hará el ordenador será analizar los bits:

  • Si el primer bit es un cero, el byte representa un carácter
  • Si el primer bit es un uno, el byte forma parte de un carácter de varios bytes:
    • Si el segundo bit es un uno, se trata del primer byte del carácter. El número de unos antes de encontrar un cero nos dice cuantos bytes forman el carácter
    • Si el segundo bit es un cero, es un byte de continuación.

Veamos un ejemplo. Supongamos que al recorrer un texto encontramos un byte 11000011. Como el primer bit es un uno, asumimos que hay más bytes, y como al principio hay dos unos, deducimos que el carácter está formado por dos bytes, y que el segundo viene a continuación.

En resumen, en UTF-8 tenemos los siguientes patrones:

  • Caracteres de 1 byte: 0nnnnnnn
  • Caracteres de dos bytes: 110nnnnn 10nnnnnn
  • Caracteres de tres bytes: 1110nnnn 10nnnnnn 10nnnnnn
  • Caracteres de cuatro bytes: 11110nnn 10nnnnnn 10nnnnnn 10nnnnnn