8.15. Escribir en un fichero binario
Curso: Programación en C# (2015), por Nacho Cabanes
8.15. Escribir en un fichero binario
Para escribir en un FileStream, usaremos órdenes similares a las que empleábamos para leer de él:
- Un método WriteByte, para escribir sólo un byte, o bien...
- Un método Write, para escribir un bloque de información (desde cierta posición de un array -normalmente 0-, y con cierto tamaño).
Además, a la hora de abrir el fichero, tenemos dos alternativas:
- Abrir un fichero existente con "OpenWrite".
- Crear un nuevo fichero con "Create".
Vamos a ver un ejemplo que junte todo ello: crearemos un fichero, guardaremos datos, lo leeremos para comprobar que todo es correcto, añadiremos al final, y volveremos a leer:
?// Ejemplo_08_15a.cs // Ficheros binarios: escritura en FileStream // Introducción a C#, por Nacho Cabanes using System; using System.IO; public class Ejemplo_08_15a { const int TAMANYO_BUFFER = 10; public static void Main() { FileStream fichero; string nombre; byte[] datos; nombre = "datos.dat"; datos = new byte[TAMANYO_BUFFER]; // Damos valores iniciales al array for (byte i=0; i<TAMANYO_BUFFER; i++) datos[i] = (byte) (i + 10); try { // Primero creamos el fichero, con algun dato fichero = File.Create( nombre ); fichero.Write(datos, 0, TAMANYO_BUFFER); fichero.Close(); // Ahora leemos dos datos fichero = File.OpenRead(nombre); Console.WriteLine("El tamaño es {0}", fichero.Length); fichero.Seek(2, SeekOrigin.Begin); int nuevoDato = fichero.ReadByte(); Console.WriteLine("El tercer byte es un {0}", nuevoDato); fichero.Seek(-2, SeekOrigin.End); nuevoDato = fichero.ReadByte(); Console.WriteLine("El penultimo byte es un {0}", nuevoDato); fichero.Close(); // Ahora añadimos 10 datos más, al final fichero = File.OpenWrite(nombre); fichero.Seek(0, SeekOrigin.End); fichero.Write(datos, 0, TAMANYO_BUFFER); // y modificamos el tercer byte fichero.Seek(2, SeekOrigin.Begin); fichero.WriteByte( 99 ); fichero.Close(); // Volvemos a leer algun dato fichero = File.OpenRead(nombre); Console.WriteLine("El tamaño es {0}", fichero.Length); fichero.Seek(2, SeekOrigin.Begin); nuevoDato = fichero.ReadByte(); Console.WriteLine("El tercer byte es un {0}", nuevoDato); fichero.Close(); } catch (Exception e) { Console.WriteLine("Problemas: "+e.Message); return; } } }
(Nota: existe una propiedad "CanWrite" que nos permite saber si se puede escribir en el fichero).
Si queremos que escribir datos básicos de C# (float, int, etc.) en vez de un array de bytes, podemos usar un "BinaryWriter", que se maneja de forma similar a un "BinaryReader", con la diferencia de que no tenemos métodos WriteByte, WriteString y similares, sino un único método "Write", que se encarga de escribir el dato que le indiquemos, sea del tipo que sea:
?// Ejemplo_08_15b.cs // Ficheros binarios: escritura en BinaryWriter // Introducción a C#, por Nacho Cabanes using System; using System.IO; public class Ejemplo_08_15b { public static void Main() { BinaryWriter ficheroSalida; BinaryReader ficheroEntrada; string nombre; // Los datos que vamos a guardar/leer byte unDatoByte; int unDatoInt; float unDatoFloat; double unDatoDouble; string unDatoString; Console.Write("Introduzca el nombre del fichero a crear: "); nombre = Console.ReadLine(); Console.WriteLine("Creando fichero..."); // Primero vamos a grabar datos try { ficheroSalida = new BinaryWriter( File.Open(nombre, FileMode.Create)); unDatoByte = 1; unDatoInt = 2; unDatoFloat = 3.0f; unDatoDouble = 4.0; unDatoString = "Hola"; ficheroSalida.Write(unDatoByte); ficheroSalida.Write(unDatoInt); ficheroSalida.Write(unDatoFloat); ficheroSalida.Write(unDatoDouble); ficheroSalida.Write(unDatoString); ficheroSalida.Close(); } catch (Exception e) { Console.WriteLine("Problemas al crear: "+e.Message); return; } // Ahora vamos a leerlos Console.WriteLine("Leyendo fichero..."); try { ficheroEntrada = new BinaryReader( File.Open(nombre, FileMode.Open)); unDatoByte = ficheroEntrada.ReadByte(); Console.WriteLine("El byte leido es un {0}", unDatoByte); unDatoInt = ficheroEntrada.ReadInt32(); Console.WriteLine("El int leido es un {0}", unDatoInt); unDatoFloat = ficheroEntrada.ReadSingle(); Console.WriteLine("El float leido es un {0}", unDatoFloat); unDatoDouble = ficheroEntrada.ReadDouble(); Console.WriteLine("El double leido es un {0}", unDatoDouble); unDatoString = ficheroEntrada.ReadString(); Console.WriteLine("El string leido es \"{0}\"", unDatoString); Console.WriteLine("Volvamos a leer el int..."); ficheroEntrada.BaseStream.Seek(1, SeekOrigin.Begin); unDatoInt = ficheroEntrada.ReadInt32(); Console.WriteLine("El int leido es un {0}", unDatoInt); ficheroEntrada.Close(); } catch (Exception e) { Console.WriteLine("Problemas al leer: "+e.Message); return; } } }
El resultado de este programa es:
Introduzca el nombre del fichero a crear: 1234 Creando fichero... Leyendo fichero... El byte leido es un 1 El int leido es un 2 El float leido es un 3 El double leido es un 4 El string leido es "Hola" Volvamos a leer el int... El int leido es un 2
En este caso hemos usado "FileMode.Create" para indicar que queremos crear el fichero, en vez de abrir un fichero ya existente. Los modos de fichero que podemos emplear en un BinaryReader o en un BinaryWriter son los siguientes:
- CreateNew: Crear un archivo nuevo. Si existe, se produce una excepción IOException.
- Create: Crear un archivo nuevo. Si ya existe, se sobrescribirá.
- Open: Abrir un archivo existente. Si el archivo no existe, se produce una excepción System.IO.FileNotFoundException.
- OpenOrCreate: Se debe abrir un archivo si ya existe; en caso contrario, debe crearse uno nuevo.
- Truncate: Abrir un archivo existente y truncarlo para que su tamaño sea de cero bytes.
- Append: Abre el archivo si existe y se desplaza hasta el final del mismo, o crea un archivo nuevo si no existe.
Ejercicios propuestos:
Ejercicio propuesto 8.15.1: Crea una copia de un fichero EXE. La copia debe tener el mismo nombre y extensión BAK.
Ejercicio propuesto 8.15.2: Crea un programa que "encripte" el contenido de un fichero BMP, volcando su contenido a un nuevo fichero, en el que intercambiará los dos primeros bytes. Para desencriptar, bastará con volver a intercambiar esos dos bytes, volcando a un tercer fichero.
Actualizado el: 22-03-2015 17:08