miércoles, 30 de abril de 2014

Receta No. 2-3 en C#: Conversión de Tipos Numéricos a Arreglos de Bytes

Índice

0. Introducción
1. Problema
2. Solución
3. Discusión de la Solución
4. Práctica: Código Fuente C#
5. Conclusiones
6. Glosario
7. Enlaces & Literatura

0. Introducción

En la receta anterior -Receta No. 2-2 en C#: Codificar una Cadena deCaracteres usando un Sistema de Codificación Alternativo- usamos un recurso del Framework .NET para realizar la conversión de un flujo de cadena de bytes a un flujo de caracteres que representa cada byte en el arreglo: BitConverter.ToString(byte[]). Vamos a aprovechar ahora para preparar una receta utilizando este artefacto entre otros, precisamente, vamos a convertir tipos numéricos a arreglo de bytes (o viceversa).

1. Problema

Necesitamos de un artefacto del Framework .NET para convertir tipos de datos integrales a arreglo de bytes. (El proceso contrario, es decir, de arreglo de bytes a tipos integrales también debe ser posible).

2. Solución

La clase BitConverter [2] provee la maquinaria (conjunto de métodos estáticos) para realizar este tipo de conversión: tipos por valor a arreglo de bytes. También se descubrió que posee métodos para realizar el proceso reversible: convertir un arreglo de bytes a un tipo por valor.

3. Discusión de la Solución

Ya dijimos que la clase BitConverter provee métodos para lograr este tipo de conversión. En especial hay un método GetBytes [4] que posee varias versiones sobrecargadas.
Versiones sobrecargada método GetBytes de BitConverter
Figura 1. Versiones sobrecargada método GetBytes de BitConverter [4].
Observemos en la Figura 1 que bytes tiene soporte para todos los tipos de datos por valor. A saber:
  • Boolean
  • Char
  • Double
  • Int16
  • Int32
  • Int64
  • Single
  • UInt16
  • IInt32
  • UInt64
Tenemos que saber que para la conversión de un valor de punto flotante debe realizarse utilizando otro recurso (como veremos en la parte práctica):

System.IO.MemoryStream [5]

Para lograrlo, pasamos como argumento un objeto de la clase anterior sobre un objeto del tipo BinaryWriter [6] (namespace: System.IO).

4. Práctica: Código Fuente C#

En este ejemplo vamos a demostrar el uso de la clase BitConverter, y de otros dos recursos MemoryStream (junto con BinaryWriter [6], y BinaryReader [7]) y BitConverter para lograr la conversión de un tipo numérico de punto flotante a un arreglo de bytes. La operación contraria, igualmente.


[Nota: El código se haya auto-explicado con los comentarios XML y los en línea.]

Compilación:


  1. csc /target:exe ConvertidorNumeroArregloBytes.cs

> Prueba de ejecución.

Resultados:

01 (arreglo bytes) = True (booleano)
21-05-00-00 (arreglo bytes) = 1313 (entero)
83-24-6A-E7-B9-1D-01-00-00-00-00-00-00-00-0E-00 (arreglo bytes) = 3.14159265358979 (decimal)

Notas acerca de la salida:

Al realizar una invocación del método BitConverter.ToString(byte[]) se generará una cadena que representa los bytes que contiene el arreglo. Cada byte es representado en el sistema numérico hexadecimal. Cada byte se separa por un guión; como en:

21-05-00-00 (arreglo bytes) = 1313 (entero)

Conclusiones

En esta receta hemos aprendido a convertir tipos por valor a arreglos de bytes. El proceso contrario también lo practicamos en el ejemplo de la sección. Además vimos que el uso conjunto de las clases MemoryStream, BinaryWriter, BinaryReader (todas pertenecen al namespace: System.IO) permite realizar la conversión de valores decimales (e.g., 3.14159265358979M) a arreglos de bytes, y viceversa.

Glosario

  • Arreglo
  • Bytes
  • Convertidor
  • XML

Enlaces & Literatura

[1]: Visual C# 2010 Recipes by Allen Jones and Adam Freeman. Copyright 2010 Allen Jones and Adam Freeman, 978-1-4302-2525-6.
[2]: BitConverter Class (System) - http://msdn.microsoft.com/en-us/library/system.bitconverter%28v=vs.110%29.aspx
[3]: Receta No. 2-2 en C#: Codificar una Cadena de Caracteres usando Sistema de Codificación Alternativo | OrtizOL - Experiencias Construcción Software (xCSw) - http://ortizol.blogspot.com/2014/04/receta-no-2-2-en-c-codificar-una-cadena.html
[4]: BitConverter.GetBytes Method (System) - http://msdn.microsoft.com/en-us/library/system.bitconverter.getbytes(v=vs.110).aspx
[5]: MemoryStream Class (System.IO) - http://msdn.microsoft.com/en-us/library/system.io.memorystream(v=vs.110).aspx
[6]: BinaryWriter Class (System.IO) - http://msdn.microsoft.com/en-us/library/system.io.binarywriter(v=vs.110).aspx
[7]: BinaryReader Class (System.IO) - http://msdn.microsoft.com/en-us/library/system.io.binaryreader%28v=vs.110%29.aspx


M

Caso VS 2013: Problema Habilitación Hyper-V para Emulador de Windows Phone

Tabla de Contenido

1. Descripción del Caso
2. Solución del caso
3. Recursos

1. Descripción del Caso

Mientras que configuraba el ambiente de desarrollo Visual Studio 2013 para el desarrollo y demostraciones de las aplicaciones móviles Windows Phone, el programa de instalación de generó el siguiente mensaje de error:
Problema habilitación Hyper-V para Emulador de Windows Phone
Figura 1. Problema habilitación Hyper-V para Emulador de Windows Phone.
Esto no va a permitir que ejecutemos el emulador de Windows Phone en las pruebas que realizamos a las aplicaciones que desarrollemos en el IDE.

Mensaje del error:
Failed to enable Hyper-V. For more information, see MSDN article at "http://go.microsoft.com/fwlink/?LinkId=252007".
Ambiente:

  • Máquina Virtual VMware [2]
    • Windows 8.1 x64
    • 4GB RAM
    • HDD 90GB

2. Solución del Caso

Procedemos de la siguiente manera para hallar la solución:

  1. Apagamos la máquina virtual
  2. Editamos la configuración
  3. Vamos a la sección Processors
  4. Aquí establecemos el número de procesador a dos, y el número de cores por procesador a 2:

    Number of processors: 2
    Number of cores per processor: 2

  5. Guardamos
Actualización procesador máquina virtual
Figura 2. Actualización procesador máquina virtual.
La siguiente parte de la solución consiste en editar el archivo de configuración de la máquina virtual.
  1. Debemos tener VMware Workstation cerrado.
  2. Abrimos el archivo con extensión .vmx, en mi caso: Windows 7 x64 - Xamarin.vmx
  3. Agregamos esta línea al final de archivo:

    hypervisor.cpuid.v0 = "FALSE"

  4. Guardamos cambios
Hechas estas dos tareas ya podemos iniciar nuestra máquina virtual e iniciar nuestro emulador de Windows Phone.

Recursos

[1]: OrtizOL | AndroidDEV - http://ortizolandroidev.blogspot.com
[2]: VMware Workstation: Run Multiple OS, Linux, Windows 8 & More; | United States - http://www.vmware.com/products/workstation/
[3]: Hyper-V - Wikipedia, the free encyclopedia - http://en.wikipedia.org/wiki/Hyper-V


E

martes, 29 de abril de 2014

Receta No. 2-2 en C#: Codificar una Cadena de Caracteres usando Sistema de Codificación Alternativo

Tabla de Contenido

0. Introducción
1. Problema
2. Solución
3. Discusión de la Solución
4. Práctica: Código Fuente C#
5. Conclusiones
6. Glosario
7. Enlaces & Literatura

0. Introducción

Pasemos a otra receta. En esta receta vamos a aprender acerca de la transformación (o conversión) entre sistemas de codificación de caracteres. Veremos que el sistema que utiliza la Common Language Runtime (CLR) para representar y manipular cadenas caracteres es UTF-16. ¿Cuál será la utilidad directa de esta receta? Sencillamente cuando nos enfrentemos al intercambio de datos entre sistemas heterogéneos, será necesario contar con un mecanismo de conversión de datos entre dos o más sistemas de información. Empecemos ahora mismo.

1. Problema

Como mencionamos en la introducción una necesidad explícita de los sistemas informáticos es el intercambio de información. Del departamento de TI nos informan que debido a cambios estratégicos en el modelo de partners, se requiere hacer una integración entre dos sistemas: el SistemaA (que es propio de nuestra organización), y la del nuevo partner extranejero, el SistemaB. Estos sistemas van a intercambiar información constantemente, pero debido a casos de compatibilidad relacionados con la regionalización de los sistemas informáticos, esto no es posible.

2. Solución

El arquitecto de software ha encontrado los recursos clave en nuestra plataforma de desarrollo (Microsoft .NET Framework) para llevar a cabo la tarea de conversión de cadenas de caracteres (datos de intercambio) entre los diferentes sistemas de codificación (códigos de página) de los sistemas de las dos organizaciones. A continuación, en la siguiente sección vamos a ver esto con más detalle.

3. Discusión de la Solución

Se mencionó en la introducción que la Common Language Runtime (CLR) manipula y representa cadenas de caracteres utilizando el código de página [2, 3] (o esquema de codificación de caracteres, o, ~character-encoding scheme) a través del esquema UTF-16 [6]. Debido a que este es el sistema por defecto que utiliza la CLR, la situación que requiera intercambiar datos con otros sistema de información que utilicen diferentes tipos de esquemas (e.g., ASCII (20127), UTF-7 (65000), UTF-8 (65001), BigEndianUnicode (1201), Unicode (12000), para sistemas operativos Windows (1252)) tenemos que recurrir a artefactos del Framework para realizar las conversiones requeridas.

En la Figura 1 se muestra el listado de clases del Framework para la codificación de caracteres.
Clases de codificación de caracteres en .NET Framework.
Figura 1. Clases de codificación de caracteres en .NET Framework [1].
Continuando, .NET Framework posee la clase abstracta Encoding [7]  que permite obtener una instancia de uno de los sistemas de codificación enumerados en la Figura 1 a través del método GetCoding [4]. Este método tiene varias versiones sobrecargadas. Solo voy a mencionar dos:

public static Encoding GetEncoding(int codepage)

-y-

public static Encoding GetEncoding(string name)

La primera versión sobrecargada permite pasar un número entero (int) que representa el identificador código de página (e.g., 20127 (ASCII), 65001 (Windows OS), y 0 (predeterminado)).

En tanto, la segunda versión permite pasar una cadena de caracteres (string) que representa el código de página (e.g., "utf-32""utf-7").

En la Figura 1 también se enlistan una serie de propiedades estáticas de la clase Encoding que representan los códigos de página:
  • Encoding.UTF7 [8]
  • Encoding.UTF8 [9]
  • Encoding.UTF32 [10]
[Nota: Para conocer el listado completo de estas propiedades ir a [11].]

El siguiente a paso a realizar (después de haber creado el objeto que representa el esquema actual de códificación de nuestro sistema), es hora de pasar a convertir el flujo de caracteres en un flujo de bytes a través del método GetBytes [12] (FQCN: System.Text.Encoding.GetBytes).

El método opuesto a la operación es GetString [13] que permite obtener la cadenas de caracteres del flujo de caracteres a partir de un flujo o secuencia de bytes.

4. Práctica: Código Fuente C#

Veamos en el siguiente ejemplo cómo convertir una cadena de caracteres codificada en UTF-16 (esquema de la CLR) en esquemas (códigos de página) de diferente (i.e., UTF-8, ASCII).


Compilación:

  1. csc /target:exe /out:ConversionEsquemasCaracteres.exe ./ConversionEsquemasCaracteres.cs

Ejecución:

  1. ./ConversionEsquemasCaracteres.exe

El archivo de texto de salida (salida.txt):

5. Notas Finales

Vale apuntar que la clase Encoding posee el método Convert (static). Este método  tiene una versión sobrecargada con la siguiente firma:

public static byte[] Convert(Encoding srcEncoding, Encoding dstEncoding, byte[] bytes)

Lo que nos va a facilitar y agilizar el proceso de conversión entre dos sistemas de codificación de caracteres.

byte[] bytesAscii = Encoding.Convert(Encoding.Unicode, Encoding.ASCII, bytesUnicode);

5. Conclusiones

La preparación de esta receta nos ha enseñado a manipular cadenas de caracteres con diferentes esquemas de caracteres (códigos de página - code page) a través de los artefactos que nos brinda el Framework .NET. Esto nos da la oportunidad de intercambiar datos entre distintos sistemas de información de forma muy fácil y práctica. En el ejemplo presentado en la sección 4 vimos la conversión de un texto en UTF-16 (predetermiando de la CLR) a otros (UTF8 y ASCII), y de éstos últimos al esquema de caracteres por defecto (UTF-16). Los resultados se muestra en el archivo de salida (salida.txt).

6. Glosario

  • CLR
  • Code page
  • Código de página
  • Common Language Runtime
  • FQCN: Fully Qualified Class Name
  • Intercambio de información
  • Regionalización

7. Enlaces & Literatura

[1]: Visual C# 2010 Recipes by Allen Jones and Adam Freeman. Copyright 2010 Allen Jones and Adam Freeman, 978-1-4302-2525-6.
[2]: Code page, the free encyclopedia - http://en.wikipedia.org/wiki/Code_page
[3]: Página de códigos, la enciclopedia libre - http://es.wikipedia.org/wiki/P%C3%A1gina_de_c%C3%B3digos
[4]: Encoding.GetEncoding Method (Int32) (System.Text) - http://msdn.microsoft.com/en-us/library/wzsz3bk3%28v=vs.110%29.aspx
[5]: Text Encoding Tables Index - http://www.string-functions.com/encodingindex.aspx
[6]: UTF-16, the free encyclopedia - http://en.wikipedia.org/wiki/UTF-16
[7]: Encoding Class (System.Text) - http://msdn.microsoft.com/en-us/library/system.text.encoding%28v=vs.110%29.aspx
[8]: Encoding.UTF7 Property (System.Text) - http://msdn.microsoft.com/en-us/library/system.text.encoding.utf7(v=vs.110).aspx
[9]: Encoding.UTF8 Property (System.Text) - http://msdn.microsoft.com/en-us/library/system.text.encoding.utf8(v=vs.110).aspx
[10]: Encoding.UTF32 Property (System.Text) - http://msdn.microsoft.com/en-us/library/system.text.encoding.utf32(v=vs.110).aspx
[11]: Encoding Properties (System.Text) - http://msdn.microsoft.com/en-us/library/system.text.encoding_properties(v=vs.110).aspx
[12]: Encoding.GetBytes Method (String) (System.Text) - http://msdn.microsoft.com/en-us/library/ds4kkd55(v=vs.110).aspx
[13]: Encoding.GetString Method (System.Text) - http://msdn.microsoft.com/en-us/library/system.text.encoding.getstring(v=vs.110).aspx


M

Restricciones sobre los Modificadores de Acceso en C#

Tabla de Contenido

0. Introducción
1. Restricción en Jerarquía de Herencia
2. Inconsistencias de Accesibilidad
3. Conclusiones
4. Glosario
5. Enlaces & Literatura

0. Introducción

En artículos previos -Modificadores de Acceso en C#, Friend Assemblies en C#, y Superposicion de Modificadores de Acceso en C#- hemos visto varias de las propiedades y funcionalidades de los modificadores de acceso en C#; y en este artículo vamos a incluir otro concepto relacionado con el grado de acceso de un modificador. Veremos que esto es importante en la jerarquía de herencia de tipos.

1. Restricción en Jerarquía de Herencia

En el artículo -La Clase Object y sus Miembros en C#- aprendimos que varios de los métodos disponibles de la clase Object pueden ser sobreescritos, por poner un caso: ToString. Recordemos su firma:

public virtual string ToString()

Este método puede ser sobreescrito por cualquier subclase que herede de Object (por la naturaleza jerárquica del Framework .NET, todas las clases heredan de este superclase).

Definición parcial de la clase Object:

public class Object
{
// Definiciones restantes sobre la clase Object

public virtual string ToString();
}

Ahora tenemos la clase Subclase que hereda implícitamente de Object:

public class Subclase
{
// Definiciones restantes sobre la clase Object

public override string ToString() // Esto es correcto.
  {
// Implementación de ToString en Subclase
}
}

La redefinición de ToString en la clase Subclase es correcta, dado que el modificador de acceso del método sobreescrito coincide con el de ToString definido en la clase Object.

Por otro lado, si hacemos algo como esto:

public class Subclase2
{
// Definiciones restantes sobre la clase Object

protected override string ToString() // Esto es correcto.
  {
// Implementación de ToString en Subclase
}
}

Vamos a tener problemas. Para mirar esto en acción:


Esto se debe a que se está cambiando el grado de acceso del modificador en el método ToString en la subclase Subclase2. Error:

error CS0507: `Subclase2.ToString()': cannot change access modifiers when overriding `public' inherited member `object.ToString()'

2. Inconsistencias de Accesibilidad

Si tenemos la clase llamada B, y esta clase hereda de A, y A tiene un modificador de acceso más restrictivo que el de la subclase BB está obligado a utilizar el mismo modificador, o, uno más restrictivo. Me explico mejor:

internal class A
{
// Miembros de la clase A
}

public class B : A
{
// Miembros de la clase B
}

Esto nos va generar el siguiente error

error CS0060: Inconsistent accessibility: base class `A' is less accessible than class `B'


Esta inconsistencia -CS0060 [7]- también la podemos relacionar con la que se produce al intentar cambiar el modificador de acceso en una jerarquía de herencia, como en la sección anterior -CS0507 [8]-.

Esto no ocurre si vamos de un modificador menos restrictivo a uno más restrictivo, como en:

public class A
{
// Miembros de la clase A
}

internal class B : A
{
// Miembros de la clase B
}

Con esta definición no vamos a tener ningún error en tiempo de compilación.

Conclusiones

Aprendimos acerca de las inconsistencias que pueden surgir cuando manipulamos incorrectamente los modificadores de acceso en una jerarquía de herencia; por ejemplo, el cambiar el modificador de acceso con grado restrictivo superior a uno inferior: internal -> public. Lo contrario, public -> internal, sí está permitido. Es importante cuidarnos de estas inconsistencias cuando estamos definiendo nuestros tipos, o creando una jerarquía de herencia.

Glosario


  • Accesibilidad
  • Herencia
  • Modificador de acceso
  • Restricción

Enlaces & Literatura

[1]: C# 5.0 in a Nutshell by Joseph Albahari and Ben Albahari. Copyright 2012 Joseph Albahari and Ben Albahari, 978-1-449-32010-2.
[2]: Access Modifiers (C# Reference) - http://msdn.microsoft.com/en-us/library/vstudio/wxh6fsc7%28v=vs.100%29.aspx
[3]: Modificadores de Acceso en C# - http://ortizol.blogspot.com/2014/04/friend-assemblies-en-c.html
[4]: Friend Assemblies en C# - http://ortizol.blogspot.com/2014/04/friend-assemblies-en-c.html
[5]: Superposición de Modificadores de Acceso en C# - http://ortizol.blogspot.com/2014/04/superposicion-de-modificadores-de.html
[6]: La Clase Object y sus Miembros en C# - http://ortizol.blogspot.com/2014/04/la-clase-object-y-sus-miembros-en-c.html
[7]: Compiler Error CS0060 - http://msdn.microsoft.com/en-us/library/5732hs83%28v=vs.90%29.aspx
[8]: Compiler Error CS0507 - http://msdn.microsoft.com/en-us/library/vstudio/41k1ad8b%28v=vs.100%29.aspx


J