Ir al índice de .NET Cómo... en .NET
 

Leer y escribir en ficheros de texto

 
Publicado el 09/Ene/2007
Actualizado el 09/Ene/2007
Autor: Guillermo 'guille' Som

En este artículo te explico cómo leer y guardar cosas en ficheros de texto usando funciones y clases del propio .NET Framework. Y como de costumbre, con código tanto para Visual Basic como para C#.

 

Introducción:

Una de las operaciones más comunes o al menos que se hacen con bastante frecuencia en cualquier aplicación es la de leer y escribir en ficheros, particularmente de texto, es decir, ficheros normales y corrientes, sin contenidos especiales.

Nota:
De cómo leer y escribir en ficheros que no sean "texto plano" nos ocuparemos en otra ocasión.

En este artículo veremos cómo realizar esas operaciones usando exclusivamente funciones y clases del propio .NET Framework. Aclaro esto, porque en Visual Basic se pueden usar tanto las clases del propio .NET como las definidas en la librería/espacio de nombres Microsoft.VisualBasic.

 

Los formatos (codificación) de los ficheros

Antes de empezar "de verdad" con la forma de leer y escribir en los ficheros mediante las clase de .NET, debemos saber que en .NET se pueden leer y escribir los ficheros usando diferentes codificaciones.

No te voy a explicar qué es eso de la codificación, ya que en la ayuda lo puedes leer, lo que te voy a decir es que en .NET, de forma predeterminada, el formato o codificación usado para leer o escribir en los ficheros es UTF-8.

¿Qué problema hay con esto?
Ninguno, al menos si siempre lees y escribes usando las clases de .NET, pero si tu intención es poder leer un fichero guardado, por ejemplo, con una aplicación de Visual Basic 6 (o el Notepad de Windows), o quieres que lo que tu guardes se pueda abrir también con cualquier otra aplicación, deberás tener cuidado con la codificación usada.
Al menos si el contenido de ese fichero tiene caracteres como la eñe, vocales acentuadas, signos de apertura de admiración o interrogación, etc., ya que en esos casos, el formato usado por defecto por otras aplicaciones para Windows no será el adecuado, y esos caracteres no se leerán correctamente.

Por tanto, si decides que lo que vas a guardar o leer debe ser "compatible", tendrás que usar la codificación predeterminada de Windows (ANSI), esa codificación puedes indicarla mediante la clase Encoding (definida en el espacio de nombres System.Text) y usando el valor Default, después verás ejemplos de cómo usar esos valores a la hora de leer o de escribir en un fichero.

 

Leer y escribir ficheros de texto

Leer y escribir en ficheros de texto es lo más sencillo del mundo, (al menos cuando se sabe cómo hacerlo, je, je), ya que lo podemos hacer usando un par de líneas de código.

Veamos un ejemplo de cómo guardar en un fichero el contenido de una cadena de texto:

Visual Basic:

Const fic As String = "E:\tmp\Prueba.txt"
Dim texto As String = "Érase una vez una vieja con un moño..."

Dim sw As New System.IO.StreamWriter(fic)
sw.WriteLine(texto)
sw.Close()

 

C#:

const string fic = @"E:\tmp\Prueba.txt";
string texto = "Érase una vez una vieja con un moño...";

System.IO.StreamWriter sw = new System.IO.StreamWriter(fic);
sw.WriteLine(texto);
sw.Close();

 

Como puedes comprobar, lo único que necesitamos es crear un objeto del tipo StreamWriter (definido en el espacio de nombres System.IO), pasarle al constructor el nombre del fichero en el que queremos guardar y usar el método WriteLine al que le indicamos como argumento la cadena que queremos guardar.

 

Ahora vamos a leer de un fichero y asignaremos el contenido del mismo a una variable.
El código para Visual Basic y C# sería el siguiente:

Visual Basic:

Const fic As String = "E:\tmp\Prueba.txt"
Dim texto As String

Dim sr As New System.IO.StreamReader(fic)
texto = sr.ReadToEnd()
sr.Close()

Console.WriteLine(texto)

 

C#:

const string fic = @"E:\tmp\Prueba.txt";
string texto;

System.IO.StreamReader sr = new System.IO.StreamReader(fic);
texto = sr.ReadToEnd();
sr.Close();

Console.WriteLine(texto);

 

En este caso también es muy simple, ya que solo necesitamos usar un objeto del tipo StreamReader, (también definido en el espacio de nombres System.IO) al que le indicamos de que fichero queremos leer y por medio del método ReadToEnd leemos todo el contenido, el cual asignamos a la variable que usemos en la asignación.

 

En estos dos ejemplos al no indicar lo contrario estamos usando la codificación predeterminada, es decir, UTF-8, por tanto, si escribimos primero en ese fichero y después lo leemos, el texto se mostrará correctamente, a pesar de que en el primer ejemplo hayamos usado vocales acentuadas y eñes.

Además de que al usar la clase StreamWriter de esa forma, si había un fichero con ese mismo nombre, se eliminará y se quedará el que acabamos de escribir, es decir, se sustituye el contenido del fichero.

 

Anexar contenido a un fichero existente

Antes de ver otras cosas, veamos cómo agregar contenido a un fichero, es decir, si ese fichero existe, lo que haremos es añadir más contenido, de forma que después de escribir, lo que tendrá será lo que antes hubiere más lo que ahora escribamos.

Para conseguir esto lo único que tenemos que hacer es indicar en el constructor de la clase StreamWriter un segundo argumento con un valor verdadero.
De esa forma, si el fichero existe, se añadirá el texto al final de lo que ya tuviera. Si el fichero no existe, simplemente se creará y se guardará el texto actual, pero no dará error de que no existe.

Veamos el código para añadir texto a un fichero existente (o crearlo si no existe):

Visual Basic:

Const fic As String = "E:\tmp\Prueba.txt"
Dim texto As String = "Pablito tenía una moto con un pito."

Dim sw As New System.IO.StreamWriter(fic, True)
sw.WriteLine(texto)
sw.Close()

 

C#:

private static void agregarTexto() {
    const string fic = @"E:\tmp\Prueba.txt";
    string texto = "Pablito tenía una moto con un pito.";
 
    System.IO.StreamWriter sw = new System.IO.StreamWriter(fic, true);
    sw.WriteLine(texto);
    sw.Close();
}

 

Como ves lo único que hay que hacer es indicar como segundo argumento del constructor de la clase StreamWriter un valor verdadero, y de esa forma le indicamos que queremos agregar el texto al fichero.
Si en vez de usar un valor verdadero, indicas un valor falso (false) el comportamiento será como el del primer ejemplo, es decir, se sobrescribirá el fichero eliminando lo que antes hubiera.

 

Usar una codificación específica

Como te he comentado antes, si no indicamos lo contrario, los ficheros se leerán y se guardarán usando la codificación UTF-8. Pero si queremos usar una distinta, debemos indicarlo de forma expresa.

Por ejemplo, si queremos leer ficheros escritos por otros programas que usan la codificación estándar de Windows, por ejemplo los ficheros creados con Visual Basic 6.0, debemos indicar que NO queremos usar el formato predeterminado, esto lo haremos de la siguiente forma:

Visual Basic:

Const fic As String = "E:\tmp\Prueba2.txt"
Dim texto As String

Dim sr As New System.IO.StreamReader(fic, System.Text.Encoding.Default)
texto = sr.ReadToEnd()
sr.Close()

Console.WriteLine(texto)

 

C#:

const string fic = @"E:\tmp\Prueba2.txt";
string texto;

System.IO.StreamReader sr = new System.IO.StreamReader(fic, System.Text.Encoding.Default);
texto = sr.ReadToEnd();
sr.Close();

Console.WriteLine(texto);

 

En este caso lo único que debemos hacer es indicar en el constructor de la clase StreamReader un segundo argumento que es la codificación que queremos usar, en este caso System.Text.Encoding.Default.

 

Para escribir en esa codificación (o en cualquier otra) tendremos que indicar la codificación a usar en el tercer argumento del constructor de la clase StreamWriter, ya que en el segundo debemos indicar si queremos agregar el texto a lo que ya tuviera o bien crear el fichero usando solo el contenido que queremos guardar.
En caso de que queramos crear un fichero con el contenido que tenemos en una variable, usaremos el siguiente código:

Visual Basic:

Const fic As String = "E:\tmp\Prueba2.txt"
Dim texto As String = "Érase una vez una vieja con un moño..."

Dim sw As New System.IO.StreamWriter(fic, False, System.Text.Encoding.Default)
sw.WriteLine(texto)
sw.Close()

 

C#:

const string fic = @"E:\tmp\Prueba2.txt";
string texto = "Érase una vez una vieja con un moño...";

System.IO.StreamWriter sw = new System.IO.StreamWriter(fic, false, System.Text.Encoding.Default);
sw.WriteLine(texto);
sw.Close();

 

Por supuesto, si lo que queremos hacer es agregar el texto al fichero, en vez de usar false en el segundo argumento, debemos usar true.

Y si en vez de usar el valor "Default" queremos usar otro tipo de codificación, lo indicaremos en el tercer argumento, seleccionando uno de los valores de la clase Encoding.

 

Debo aclarar que si usamos el valor UTF8, se guardará (o leerá) usando la codificación UTF-8, pero a la hora de guardarlo, se indicará al principio del fichero que la codificación usada es UTF-8, esto es algo que no se guarda cuando no indicamos la codificación. Es decir, se guarda en formato UTF-8, pero no se almacena nada que indique que ese es el formato del fichero.
Esto es lo que se conoce como BOM (Byte Order Marks), que no es otra cosa que una marca al principio del fichero en la que se indica la codificación usada. Las tres codificaciones que almacenan valores BOM son: UTF-8, Unicode Little-Endian y Unicode Big-Endian, estos dos últimos pueden ser UTF-16 o UTF-32 (este último solo en .NET Framework 2.0 o superior). Si quieres saber más sobre esto del BOM, puedes ver en la ayuda de Visual Studio 2005 el método GetPreamble de la clase Encoding.

 

Utilizar una codificación para leer y escribir ficheros compatibles con MS-DOS

Si quieres escribir o leer ficheros compatibles con MS-DOS (no pienses que el Guille es muy viejo, que lo es, pero ese formato también puedes usarlo si abres una ventana de comandos de Windows), puedes usar el valor 437 de la página de código, ese valor lo puedes obtener mediante el método GetEncoding de la clase Encoding.

El siguiente código servirá para leer y guardar usando esa página de código:

Visual Basic:

Private Sub guardarTexto437()
    Const fic As String = "E:\tmp\Prueba4.txt"
    Dim texto As String = "Érase una vez una vieja con un moño..."

    Dim sw As New System.IO.StreamWriter(fic, False, System.Text.Encoding.GetEncoding(437))
    sw.WriteLine(texto)
    sw.Close()

End Sub


Private Sub leerTexto437()
    Const fic As String = "E:\tmp\Prueba4.txt"
    Dim texto As String

    Dim sr As New System.IO.StreamReader(fic, System.Text.Encoding.GetEncoding(437), True)
    texto = sr.ReadToEnd()
    sr.Close()

    Console.WriteLine(texto)

End Sub

 

C#:

private static void guardarTexto437()
{
    const string fic = @"E:\tmp\Prueba4.txt";
    string texto = "Érase una vez una vieja con un moño...";

    System.IO.StreamWriter sw = 
        new System.IO.StreamWriter(fic, false, System.Text.Encoding.GetEncoding(437));
    sw.WriteLine(texto);
    sw.Close();
}


private static void leerTexto437()
{
    const string fic = @"E:\tmp\Prueba4.txt";
    string texto;

    System.IO.StreamReader sr = 
        new System.IO.StreamReader(fic, System.Text.Encoding.GetEncoding(437), true);
    texto = sr.ReadToEnd();
    sr.Close();

    Console.WriteLine(texto);
}

 

Recuerda que esa página de código (437) será válida para los ficheros creados con utilidades que trabajen con el "viejo" MS-DOS o bien los que crees directamente usando una ventana de comandos de Windows.
Pero no será muy común que la uses... aunque si te hace falta, ya sabes cómo usarla.

 

Indicar una codificación si no existe un valor BOM

Para terminar, vamos a ver cómo podemos abrir un fichero para que intente detectar el valor BOM del fichero, si es que hay alguno, y en caso de que no exista esa marca se use la codificación que indiquemos.

Esto solo se puede hacer a la hora de leer el contenido del fichero, y será útil para los casos en los que no sepamos con certeza el formato que se ha usado para guardar el fichero, de forma que si se ha usado uno de los formatos que almacenan los valores en el BOM, se use ese formato, y si el fichero no tiene esa marca se use la que nosotros indiquemos.

Visual Basic:

Private Sub guardarTextoBOM()
    Const fic As String = "E:\tmp\Prueba5.txt"
    Dim texto As String = "Érase una vez una vieja con un moño..."

    Dim sw As New System.IO.StreamWriter(fic, False, System.Text.Encoding.UTF8)
    sw.WriteLine(texto)
    sw.Close()

End Sub


Private Sub leerTextoBOM()
    Const fic As String = "E:\tmp\Prueba5.txt"
    Dim texto As String

    Dim sr As New System.IO.StreamReader(fic, System.Text.Encoding.Default, True)
    texto = sr.ReadToEnd()
    sr.Close()

    Console.WriteLine(texto)

End Sub

 

C#:

private static void guardarTextoBOM()
{
    const string fic = @"E:\tmp\Prueba5.txt";
    string texto = "Érase una vez una vieja con un moño...";

    System.IO.StreamWriter sw = 
        new System.IO.StreamWriter(fic, false, System.Text.Encoding.UTF8);
    sw.WriteLine(texto);
    sw.Close();
}


private static void leerTextoBOM()
{
    const string fic = @"E:\tmp\Prueba5.txt";
    string texto;

    System.IO.StreamReader sr = 
        new System.IO.StreamReader(fic, System.Text.Encoding.Default, true);
    texto = sr.ReadToEnd();
    sr.Close();

    Console.WriteLine(texto);
}

 

Para indicar que se use una codificación en concreto cuando no existe la marca BOM, debemos usar un valor verdadero después de indicar la codificación que queremos usar.
En este ejemplo, se usará la codificación Default si no tiene esa marca.

En el método guardarTextoBOM, se guarda usando la codificación UTF8, de esa forma puedes comprobar que aunque en leerTextoBOM se haya indicado Default, los caracteres "raros" se leerán correctamente, lo que demuestra que se está usando la codificación correcta.

Si modificas el código del método leerTextoBOM para que no se detecte la codificación usada, (quitando el tercer argumento del constructor de StreamReader), el texto se mostrará también correctamente, algo que no ocurrirá si en lugar de guardarlo como UTF-8 lo hubiésemos guardado como Default y lo leyéramos como UTF8, en ese caso, el texto mostrado sería el siguiente, que es lo que a algunos les ocurre cuando leen ficheros de Visual Basic 6.0 sin indicar el valor Encoding.Default:


?rase una vez una vieja con un mo?o...
 

 

 

Bueno, pues esto es todo por ahora, espero que ahora tenga más claro cómo leer y guardar ficheros de texto usando las clases de .NET.

En otra ocasión te explicaré cómo leer ficheros "binarios" y cómo convertir ristras de bytes en texto y viceversa, pero eso será otro día, que ya es noche ;-)))

 

Nos vemos.
Guillermo

 


Espacios de nombres usados en el código de este artículo:

System.IO
System.Text
 

Referencias:

Utilizar codificación Unicode:
Ayuda de Visual Studio 2005 (en ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.VisualStudio.v80.es/)
Ayuda de Visual Studio 2005 en línea

GetPreamble (valores BOM):
Ayuda de Visual Studio 2005
Ayuda de Visual Studio 2005 en línea

 


Código de ejemplo (comprimido):

 

No hay código de ejemplo para bajar.

 


Ir al índice principal de el Guille

Valid XHTML 1.0 Transitional ¡CSS Válido!