sábado, 11 de julio de 2015

Receta C# No. 5-8: Escritura y Lectura de un Archivo Binario

Índice

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

0. Introducción

En la receta C# anterior (Receta C# No. 5-7: Escritura y Lectura de un Archivo de Texto) aprendimos cómo utilizar varias de las clases de librería BCL para escribir sobre un archivo de texto plano, y notamos que es relativamente sencillo gracias al grado de abstracción con que han sido diseñados estos artefactos de la librería; ahora es el turno de escribir y leer sobre archivos binarios, y lo llevaremos a cabo usando dos clases: BinaryWriter y BinaryReader.

1. Problema

En lugar de escribir sobre archivos de texto plano, ahora requerimos escribir datos en archivos binarios.

2. Solución

En el nombre de espacio System.IO encontramos las clases:
  • BinaryWriter, y 
  • BinaryReader
diseñadas para la escritura de archivos binarios. El uso de estas clases se conjuga con el de FileStream la cual referencia el archivo de trabajo.

3. Discusión de la Solución

3.1 Clase BinaryWriter

La clase BinaryWriter [2] (namespace System.IO) permite escribir datos primitivos o integrales (e.g., enteros, decimales, caracteres) en formato binario. Proporciona constructores sobrecargados para establecer el sistema de codificación de caracteres, para que de este modo la escritura de cadenas de caracteres sigan el sistema de codificación establecido.

Al igual que su homólogo de escritura texto plano, StreamWriter [3], BinaryWriter provee varias versiones sobrecargadas de Write [4] para escribir valores de diferentes tipos de datos en el archivo binario. En la Tabla 1 se muestra la firma y la descripción de estos métodos sobrecargados.
Versiones sobrecargadas de BinaryWriter.Write
Tabla 1. Versiones sobrecargadas de BinaryWriter.Write [4].

3.2 Clase BinaryReader

La clase System.IO.BinaryReader [6] provee miembros para la lectura de tipo de datos primitivos desde un archivo binario. Esta lectura se realiza utilizando un sistema de codificación de caracteres como:
  • ASCII, 
  • UTF-16
  • UTF-7
  • UTF-8 (por defecto).
En [6] podemos encontrar el listado completo de miembros especialmente los métodos para leer los distintos tipos de datos primitivos. Por mencionar algunos:
  • ReadBooleaen
  • ReadByte
  • ReadDecimal
  • ReadInt16
  • ReadInt32
Esto nos conlleva a prestar cuidadosa atención cuando intentamos recuperar los datos almacenados en el archivo binario, dado que es necesario usar la versión de la firma con nombre completamente calificado: es decir, el nombre del método -Read...- seguido del tipo de dato que queremos leer -...Boolean, ...Byte, ...Decimal, etc.

Esta clase y su contraparte, BinaryWriter, implementan la interfaz IDisposable [6]:
Implementación de IDisposable
Figura 1. Implementación de IDisposable [6].

4. Práctica: Código C#

En esta parte de la receta, crearemos un archivo binario sobre el que escribiremos datos de diferente naturaleza: decimal, cadena de caracteres, y carácter.

En la sentencia using de la línea 15 creamos un objeto FileStream para referenciar el archivo a crear (FileMode.Create): ArchivoBinario.bin. En el cuerpo de declaración de using, específicamente en la línea 19, creamos un objeto BinaryWriter para la escritura de datos binarios con el método Write: decimal (línea 22), cadena de caracteres (líneas 23, y 24), y carácter (línea 25).


Finalizada la escritura de datos binarios, procedemos a crear un objeto FileStream que referencia el archivo recién creado y escrito binariamente:
  • Línea 37: Creación de objeto StreamReader para leer el contenido del archivo ArchivoBinario.bin.
  • Línea 38: Con el método WriteLine de Console mostramos en la salida estándar el contenido del archivo binario sin el procesamiento requerido para hacer que los datos sean legibles (es decir, tal como se escribieron).
  • Línea 47: Con fs.Position = 0; reposicionamos el cursor de lectura en el índice 0 sobre el archivo binario.
  • Línea 49: Creación de objeto BinaryReader para leer la representación natural del contenido del archivo, i.e., decimal (línea 51), cadena de caracteres (líneas 52, y 53), y carácter (línea 54).
Compilación:

  1. csc /target:exe LecturaEscrituraArchivoBinario.cs

Ejecución assembly:

  1. .\LecturaEscrituraArchivoBinario.exe

> Prueba de ejecución (local):
Ejecución assembly LecturaEscrituraArchivoBinario.exe
Figura 1. Ejecución assembly LecturaEscrituraArchivoBinario.exe.
Notemos que cuando intentamos abrir el archivo binario ArchivoBinario.bin en un editor de texto plano obtenemos el contenido de las Figuras 2, 3, el cual no es legible para nosotros, pues para ello hemos tenido que utilizar las abstracciones de la clase BinaryReader para generar la representación humana legible.
Vista del contenido en Notepad++
Figura 2. Vista del contenido del archivo ArchivoBinario.bin en Notepad++.
Vista del contenido del archivo ArchivoBinario.bin en Notepad
Figura 3. Vista del contenido del archivo ArchivoBinario.bin en Notepad.

5. Conclusiones

Estudiamos las clases System.IO.BinaryWriter y System.IO.BinaryReader para la escritura y lectura de archivos binarios, respectivamente. Sabemos ahora que estas clases cuentan con los miembros necesarios para permitir al programador escribir valores de tipos de datos primitivos en modo binario. En la sección práctica, creamos un ejemplo que demuestra que es mandatorio usar métodos completamente calificados para leer datos de distinta naturaleza primitiva (e.g., enteros, decimales, caracteres) en formato binario.


La receta C# que viene a continuación de esta será muy entretenida y enriquecedora: trataremos la lectura de un archivo de forma asincrónica.

6. Glosario

  • Archivo binario
  • Archivo de texto plano
  • BCL
  • Nombre de espacio
  • Sistema de codificación
  • Tipo de dato primitivo

7. Literatura & Enlaces

[1]: Visual C# 2010 Recipes by Allen Jones and Adam Freeman. Copyright 2010 Allen Jones and Adam Freeman, 978-1-4302-2525-6.
[2]: BinaryWriter Class (System.IO) - https://msdn.microsoft.com/en-us/library/system.io.binarywriter(v=vs.110).aspx
[3]: StreamWriter Class (System.IO) - https://msdn.microsoft.com/en-us/library/system.io.streamwriter(v=vs.110).aspx
[4]: BinaryWriter.Write Method (System.IO) - https://msdn.microsoft.com/en-us/library/system.io.binarywriter.write(v=vs.110).aspx
[5]: BinaryReader Class (System.IO) - https://msdn.microsoft.com/en-us/library/system.io.binaryreader(v=vs.110).aspx
[6]: IDisposable Interface (System) -
https://msdn.microsoft.com/en-us/library/system.idisposable(v=vs.110).aspx


M

No hay comentarios:

Publicar un comentario

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