viernes, 15 de abril de 2016

Cadenas de Caracteres y Manipulación de Texto en C# - Parte 5/5: Sistemas de Codificación de Texto y Unicode

Índice

1. Introducción
2. Palabras Clave
3. Sistemas de Codificación de Caracteres
3.1 Conjunto de caracteres
3.1.1 Unicode
3.1.2 ASCII
3.2 Codificación de texto
3.3 Categorías
3.3.1 Subconjuntos de Unicode
3.3.2 Esquemas de codificación estándar de Unicode
4. Sistemas de Codificación en C#
4.1 Obtención de un tipo de sistema de codificación
4.2 Codificación para archivos
4.3 Representación sobre arreglos de bytes
4.3.1 De string a bytes[]
4.3.2 bytes[] a string
4.4 Pares suplentes en UTF-16
5. Conclusiones
6. Literatura & Enlaces

1. Introducción

Última parte de la serie Cadenas de Caracteres y Manipulación de Texto en C#. En este artículo se presentan los aspectos generales de codificación de texto y el sistema de caracteres Unicode. Se describe las generalidades de Unicode y su contraste frente al clásico ASCII: espacio de caracteres. requerimiento de almacenamiento y soporte por parte de Microsoft .NET Framework. Aquí se trata, además, el proceso de obtención de objetos Encoding, manejo de entrada y salida en archivos, arreglos de bytes, y breve descripción de los sistemas codificación de caracteres disponibles en .NET.

2. Palabras Clave

  • .NET
  • Aplicación legado
  • ASCII
  • Codificador de texto
  • EBCDIC
  • Esquema de codificación
  • Sistema de codificación
  • Unicode

3. Sistemas de Codificación de Caracteres

3.1 Conjunto de caracteres

Un conjunto de caracteres es una representación de caracteres para texto o literales. Cada carácter tiene asignado un código único para ser referenciado en la unidad de asignación propia del conjunto o subconjunto de caracteres.

En la actualidad dos de los conjunto de caracteres mayoritariamente usados son Unicode y ASCII.

3.1.1 Unicode

Unicode ("Unicode", 2016) es considerado en la actualidad el conjunto de caracteres de mayor uso. Éste cuenta con una capacidad de asignación de un millón de caracteres distintos. De esta capacidad, sólo el 10% -100.000- ha sido asignado. Esta asignación corresponde con los siguientes subconjuntos de caracteres (Albahari, 2012)
  • Caracteres de casi todos los idiomas, 
  • Idiomas de culturas antiguas, 
  • Símbolos especiales

3.1.2 ASCII

ASCII es considerado uno de los sistemas de codificación de caracteres más antiguos. Tiene más 30 años existencia: su simplicidad reside en la representación de los caracteres del idioma inglés. Microsoft .NET Framework soporta este sistema y es un subconjunto de Unicode: exactamente los primeros 128 caracteres.

3.2 Codificación de texto

El proceso de codificación de texto asigna un carácter a partir de un código único a su representación binaria (Albahari, 2012). Este proceso es usado en .NET para la entrada y salida de archivos y flujos de datos binarios.

Para el último caso, un programa conocido como codificador de texto mapea el contenido de un archivo desde su representación binaria a la representación que admite Unicode para los tipos char y string.

3.3 Categorías

En Microsoft .NET Framework existen dos categorías para la clasificación de un sistema de codificación (Albahari, 2012):
  • Subconjuntos de Unicode
  • Esquemas de codificación estándar de Unicode

3.3.1 Subconjuntos de Unicode

Dos ejemplos particulares podrían ser ASCII y EBCDIC. Estos dos sistemas utilizan un juego de caracteres limitados: por ejemplo, ASCII usa un juego de caracteres de 128 -donde se incluye el alfabeto inglés, los números decimales 0-9, símbolos especiales, y otros caracteres especiales para señalización en aplicaciones legado.

3.3.2 Esquemas de codificación estándar de Unicode

Los esquemas se definen de acuerdo al manejo de espacio para la representación de caracteres. Aquí se pueden citar los siguientes esquemas (Albahari, 2012):
  • UTF-32
  • UTF-16
  • UTF-8
  • UTF-7 (obsoleto)
De estos esquemas el más utilizado es UTF-8, debido a que para asignar memoria a un carácter se puede optar entre 1 y 4 bytes para los juegos de caracteres de los diferentes idiomas existentes en el mundo. En el caso particular de ASCII, sólo es requerido 1 byte para cada carácter de los 128 disponibles.

Vale mencionar que UTF-8 es el esquema que utiliza .NET para el manejo de flujos de entrada y salida; y que además constituye el sistema mayormente usado para la codificación de archivos de texto en aplicaciones que funcionan en Internet.

En cuanto a UTF-32 y UTF-16, cada uno de estos utiliza 2 y 4 bytes respectivamente. UTF-32 no resulta eficiente en espacio utilizado por carácter, sin embargo, como se menciona en Albahari (2012), UTF-32 es eficiente para acceso aleatorio a cada carácter; esto porque cada carácter tiene el mismo tamaño en memoria.

4. Sistemas de Codificación en C#

4.1 Obtención de un tipo de sistema de codificación


En C# se cuenta con el método static Encoding.GetEnconding() ("Encoding.GetEncoding Method", 2016) que cuenta con varias versiones sobrecargadas para obtener un objeto Encoding.
Métodos sobrecargados Encoding.GetEncoding
Figura 1. Métodos sobrecargados Encoding.GetEncoding ("Encoding.GetEncoding Method", 2016).
Para comprender su uso básico se recurre a la versión con firma GetEncoding(String). Este es un ejemplo de uso que recupera el esquema de codificación UTF-8 y GB18030:

Encoding utf8 = Encoding.GetEncoding("utf-8");
Encoding gb18030 = Encoding.GetEncoding("GB18030");

Por otra parte, es necesario saber que la clase abstracta Encoding cuenta con propiedades para obtener objetos particulares de esquemas (Albahari, 2012).
Propiedades static de Encoding
Figura 2. Propiedades static de Encoding (Albahari, 2012).
El método GetEncodings() obtiene la lista de todos los sistemas de codificación soportados por Microsoft .NET Framework. Este fragmento de código obtiene toda la lista completa:

foreach(EncodingInfo encoding : Encoding.GetEncodings())
{
Console.WriteLine (encoding.Name);
}

Demostración de ejecución online (ideone.com): http://ideone.com/iUMdKm

4.2 Codificación para archivos y flujos de entrada y salida

.NET Framework usa por defecto el esquema de codificación UTF-8 para flujos de entrada y salida. Un objeto de tipo de dato Encoding es el encargado de controlar el la escritura y lectura sobre un archivo.

En la siguiente línea de código fuente se escribe el texto Recetas LINQ sobre un archivo de texto linq.txt usando el esquema de codificación UTF-8:

File.WriteAllText("Recetas LINQ", "linq.txt", Encoding.UTF8);

En caso de que se omita el tercer argumento, por defecto se utilizará UTF-8.

[Nota: En futuros artículos se ampliará el manejo de flujos de entrada y salida y su relación con los sistemas de codificación.]

4.3 Representación sobre arreglo de bytes

4.3.1 De string a byte[]

Un objeto Encoding puede representarse en un arreglo de bytes. En las siguientes líneas de código se escribe la cadena de caracteres con los números de la base decimal sobre diferentes esquemas de codificación:

byte[] bytesUtf8 = Encoding.UTF8.GetBytes("1234567890");
byte[] bytesUtf16 = Encoding.Unicode.GetBytes("1234567890");
byte[] bytesUtf32 = Encoding.UTF32.GetBytes("1234567890");

Console.WriteLine (bytesUtf8.Length); // 10
Console.WriteLine (bytesUtf16.Length); // 20
Console.WriteLine (bytesUtf32.Length); // 40

Nótese en estas últimas tres líneas que el esquema más eficiente es UTF-8: sólo ocupa 10 bytes; UTF-16 el doble -20 bytes- y UTF-32 4 veces más.

4.3.2 byte[] a string

Un arreglo de elementos tipo byte puede ser representado como una cadena de caracteres; así:

string textoFuente1 = Encoding.UTF8.GetString(bytesUtf8);
string textoFuente2 = Encoding.Unicode.GetString(bytesUtf16);
string textoFuente3 = Encoding.UTF32.GetString(bytesUtf32);

Console.WriteLine (textoFuente1);
Console.WriteLine (textoFuente2);
Console.WriteLine (textoFuente3);

Cada invocación a WriteLine() escribe el texto original, es decir 1234567890.

4.4 Pares suplentes en UTF-16

El concepto de pares suplentes (surrogate pairs) describe el requerimiento de almacenamiento por parte del esquema de codificación UTF-16. .NET Framework usa este esquema para almacenar caracteres individuales o cadenas de caracteres: un carácter puede requerir una o dos palabras ("Palabra (informática)", 2016) de 16 bits cada una, y considerando que el tipo char tiene como capacidad 16 bits entonces se hace necesario almacenamiento extra para la representación de caracteres Unicode que requieren hasta dos (2) unidades char para ser presentados.

5. Conclusiones

En este artículo C# se ha comprendido el concepto de sistema de codificación de texto. Se estudió este concepto describiendo cómo .NET usa el sistema Unicode para representar los caracteres de una cadena de caracteres , un archivo de texto. Además se presentó las alternativas de esquemas de codificación disponibles: UTF-7, UTF-8, UTF-16 y UTF-32; cada uno de estos con distintos requerimientos de almacenamiento; siendo UTF-8 el más eficiente, y usado por defecto en .NET. Al final se presentaron fragmentos de código fuente C# para conversión de arreglo de bytes a string, y viceversa.


En el próximo artículo se estudia cómo representar fechas y horas utilizando tres estructuras disponibles en el namespace System.

6. Literatura & Enlaces

Albahari, J., Albahari, B. (2012). C# 5.0 in a Nutshell. United States: O'Reilly Media.
Unicode (2016, abril 10). Recuperado desde: https://en.wikipedia.org/wiki/Unicode
Encoding.GetEncoding Method (System.Text) (2016, abril 15). Recuperado desde: https://msdn.microsoft.com/en-us/library/system.text.encoding.getencoding(v=vs.110).aspx
Palabra (informática) (2016, abril 15). Recuperado desde: https://es.wikipedia.org/wiki/Palabra_(inform%C3%A1tica)
UTF-8 (2016, abril 15). Recuperado desde: https://en.wikipedia.org/wiki/UTF-8
UTF-16 (2016, abril 15). Recuperado desde: https://en.wikipedia.org/wiki/UTF-16
UTF-32 (2016, abril 15). Recuperado desde: https://en.wikipedia.org/wiki/UTF-32


V

No hay comentarios:

Publicar un comentario

Envíe sus comentarios, dudas, sugerencias, críticas. Gracias.