Inicio > .NET Framework, Apunte, C# > Uso de FileInfo para manipular archivos

Uso de FileInfo para manipular archivos


Hace algunas lunas publiqué una entrada sobre cómo navegar la estructura de directorios utilizando la clase DirectoryInfo del espacio de nombres System.IO. Pues bien, ha llegado la hora de hacer una entrada sobre los archivos. Bueno, quizás no será una entrada muy larga como la antes mencionada, pero vale la pena tratar el tema aunque sea de forma breve.

De forma similar a los directorios, .NET Framework pone a nuestra disposición una clase que nos permitirá trabajar con archivos, tanto existentes como inexistentes. La clase, símil de los directorios, se llama FileInfo. Como cabría esperar, se le pasa como parámetro al constructor la dirección física –absoluta o relativa- al archivo sobre el que trabajaremos. Por ejemplo:

using System;
using System.IO;
...
FileInfo file = new FileInfo(@"C:\users\fgomez\test.txt");
...

Al igual que con DirectoryInfo, si el archivo no existe físicamente, no se lanzará una excepción. Empero, sí se pueden lanzar las siguientes excepciones en caso de que ciertas condiciones se cumplan.

  • ArgumentNullException, si el parámetro es nulo. La presencia de esta excepción indica que eres medio güey.
  • ArgumentException, si el parámetro presenta caracteres inválidos para un directorio, como las comillas o los signos de igualdad.
  • SecurityException indica que el usuario que ejecuta la aplicación no tiene permisos para acceder al susodicho directorio.
  • PathTooLongException, si el tamaño de la cadena del nombre excede el default para el sistema, usualmente 248 caracteres.
  • NotSupportedException, si el nombre del archivo contiene un signo de dos puntos (:).
  • UnauthorizedAccessException, si no se cuenta con permisos para acceder al archivo.

La clase nos proporciona una propiedad, Exists, que devuelve verdadero si el archivo existe físicamente o no. Cuando creamos el objeto FileInfo en realidad no abrimos el archivo. Así, debemos utilizar Exists para saber si existe el archivo físicamente, antes de abrir el flujo de datos.

Si el archivo existe físicamente, entonces podemos acceder a ciertas propiedades que nos dan una descripción más detallada sobre el mismo. De hecho, FileInfo deriva de la clase abstracta FileSystemInfo, así que tenemos algunas propiedades comunes con directorios. Sea como fuere, hablaremos sobre dichas propiedades.

Aparte de Exists, tenemos las propiedades Name y FullName. La primera te regresa el nombre del archivo mientras que la segunda te regresa la ruta completa a éste. En otras palabras, si el archivo es “C:\users\fgomez\test.txt”, Name te regresará “test.txt” mientras que FullName regresará “C:\users\fgomez\test.txt”. Luego, tenemos la propiedad Extension, que en nuestro ejemplo regresaría “txt”. Por otra parte si quisiéramos obtener el directorio sobre el que se encuentra, usamos la propiedad Directory y DirectoryName, que nos devuelven un objeto DirectoryInfo y una cadena de texto, respectivamente, representando el directorio al que el archivo pertenece.

Dos propiedades adicionales útiles son IsReadOnly, que devuelve verdadero si el archivo es de solo lectura; y Length, que nos devuelve el tamaño, en bytes, del archivo.

Adicionalmente, tenemos los atributos del archivo, en la propiedad Attributes. Ésta regresa una enumeración de tipo FileAttributes que nos da más propiedades sobre el archivo (nótese que se hereda de FileSystemInfo, por lo que esta propiedad también está disponible para cualquier directorio). Esta enumeración está marcada con el atributo FlagsAttribute, por lo que se puede realizar operaciones de bits. Por cierto, esta propiedad (así como otras que obtienen información sobre el archivo) lanza un SecurityException (definida en System.Security, por cierto) si uno no tiene permisos de lectura, y un IOException si al momento de invocarse el directorio no está disponible (usualmente por un error de Windows, aunque también puede pasar, por ejemplo, con unidades de red mapeadas como unidades de disco).

Hay otras propiedades, heredadas de FileSystemInfo que pueden ser de utilidad. En resumen, para obtener la fecha en la que el directorio fue creado, leído o modificado por última vez, utilizamos las propiedades CreationTime, LastAccessTime, LastWriteTime, respectivamente.

En aras de mostrar lo que llevamos, creo que es un buen momento para un pequeño programita que demuestre lo dicho anteriormente. Éste simplemente pide al usuario un archivo y si existe, imprime en pantalla sus propiedades.

using System;
using System.IO;
using System.Security;

class Program
{
  static void Main(string[] args)
  {
    string path = null;

    Console.WriteLine("Ingrese un archivo: ");
    path = Console.ReadLine();
    Console.WriteLine();

    try
    {
      FileInfo file = new FileInfo(path);
      if (file.Exists)
      {
        Console.WriteLine("Nombre: {0}", file.Name);
        Console.WriteLine("Nombre completo: {0}", file.FullName);
        Console.WriteLine("Directorio padre: {0}", file.DirectoryName);
        Console.WriteLine("Es de lectura: {0}", file.IsReadOnly);
        Console.WriteLine("Tamaño: {0} bytes", file.Length);
        Console.WriteLine("Atributos: {0}", file.Attributes);
        Console.WriteLine("Creado: {0}", file.CreationTime);
        Console.WriteLine("Leído: {0}", file.LastAccessTime);
        Console.WriteLine("Modificado: {0}", file.LastWriteTime);
      }
      else
      {
        Console.WriteLine("El archivo '{0}' no existe. ", path);
      }
    }
    catch (ArgumentException ex)
    {
      Console.WriteLine("El archivo '{0}' es inválido. {1}",
        path, ex.Message);
    }
    catch (PathTooLongException ex)
    {
      Console.WriteLine("El archivo '{0}' tiene muchos caracteres. {1}",
        path, ex.Message);
    }
    catch (SecurityException ex)
    {
      Console.WriteLine("No tiene permiso para acceder a '{0}'. {1}",
        path, ex.Message);
    }
    catch (NotSupportedException ex)
    {
      Console.WriteLine("El archivo '{0}' contiene caracteres inválidos. {1}",
        path, ex.Message);
    }
    catch (IOException ex)
    {
      Console.WriteLine("El directorio '{0}' no está disponible. {1}",
        path, ex.Message);
    }

    Console.ReadKey(true);
  }
}

La salida de este programa se ve algo similar a esto:

Ingrese un archivo:
c:\users\fgomez\jcesc.xlsx

Nombre: jcesc.xlsx
Nombre completo: c:\users\fgomez\jcesc.xlsx
Directorio padre: c:\users\fgomez
Es de lectura: False
Tamaño: 16737 bytes
Atributos: Archive
Creado: 04/05/2010 10:39:44 p.m.
Leído: 04/05/2010 10:39:44 p.m.
Modificado: 23/04/2010 06:12:36 p.m.

Ahora bien, la clase FileInfo provee ciertos métodos que nos permiten crear, modificar y eliminar archivos, así como copiarlos y reemplazarlos. Varios de estos métodos asumen que el archivo en cuestión existe, por lo que si no existe e intentamos invocarlos (por ejemplo, llamar a OpenRead) obtendremos una excepción FileNotFoundException. Así que buzos.

Ahora sí, principiemos. Para crear un archivo, usamos los métodos Create y CreateText. El primer método crea un archivo y nos devuelve un flujo de datos FileStream a través del cual podemos escribir bytes. El segundo método igual nos crea un archivo, pero lo abre de tal forma que podamos escribir un texto; por ello, nos devuelve un StreamWriter. Para que ambos funcionen, debemos tener permisos de lectura y escritura, y el archivo en cuestión no debe existir. El siguiente código muestra cómo hacerlo.

using System;
using System.IO;
using System.Text;
...

FileInfo file;

file = new FileInfo(@"C:\users\fgomez\temp.dat");
FileStream stream = file.Create();
byte[] buffer = Encoding.UTF8.GetBytes("Hola mundo");
stream.Write(buffer, 0, buffer.Length);
stream.Close();

file = new FileInfo(@"C:\users\fgomez\temp.txt");
StreamWriter writer = file.CreateText();
writer.Write("Hola mundo");
writer.Close();

Ambas formas en este ejemplo producen archivos con el mismo contenido. La diferencia es que en el primero, tuvimos que convertir de texto a bytes, porque un FileStream solo nos admite bytes, mientras que el StreamWriter nos facilita el trabajo al escribir texto.

Si un archivo ya existe y queremos escribir texto al final del mismo, podemos utilizar el método AppendText, que también nos regresa un StreamWriter. No existe, empero, un método similar si queremos escribir en bytes. En su lugar, utilizamos el método OpenWrite, que nos devuelve un FileStream, y luego nos posicionamos al final del flujo con el método FileStream.Seek.

Para abrir un archivo en modo lectura y modo lectura de texto, utilizamos los métodos OpenRead (que nos devuelve un FileStream) y el método OpenText (que nos devuelve un StreamReader), respectivamente. Ejemplo:

StreamReader reader = file.OpenText();
string content = reader.ReadToEnd();
reader.Close();
Console.WriteLine("Contenido texto:");
Console.WriteLine(content);

FileStream stream = file.OpenRead();
byte[] buffer = new byte[stream.Length];
stream.Read(buffer, 0, buffer.Length);
stream.Close();
content = Encoding.UTF8.GetString(buffer);
Console.WriteLine("Contenido binario:");
Console.WriteLine(content);

Ahora, si queremos abrir el archivo de modo lectura, escritura, o ambos; o bien queremos especificar el nivel de seguridad o bloquear el archivo, utilizamos el método Open. Esto, sin embargo, nos regresará un FileStream, así que tendremos que trabajar con puro byte. El siguiente código muestra cómo abrir el archivo si existe, o crearlo si no existe; tener acceso de lectura y escritura; y bloquearlo para que ninguna otra aplicación lo pueda abrir hasta que lo cerremos.

FileStream stream =
     file.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
...
stream.Close();

Y ya para finalizar, hablaremos de otros tres métodos importantes. El primero, CopyTo, nos permite copiar el archivo en cuestión a otra ubicación. Opcionalmente, nos permite especificar si queremos sobreescribir el archivo destino, en caso de que ya exista alguno con el mismo nombre.

FileInfo file = new FileInfo(@"C:\users\fgomez\temp.txt");
file.CopyTo(@"C:\users\fgomez\copy.txt", true);

El segundo método es sencillo: Delete, y nos sirve para que, si un archivo ya existe, lo podamos eliminar del disco.

FileInfo file = new FileInfo(@"C:\users\fgomez\temp.txt");
file.Delete();

Y el tercero, Replace, lo que hace es eliminar un archivo existente y reemplazarlo por el actual, además de crear una copia del eliminado. Esto es útil si queremos realizar copias temporales de un archivo, o si en lugar de copiar el archivo a una ubicación y eliminar el existente, queremos conservarlo.

Bueno, eso es todo por hoy. Ha sido una entrada larga, pero ya tienes un conocimiento general sobre manipulación de archivos. Y todo gracias a nuestra querida clase FileInfo.

Anuncios
Categorías:.NET Framework, Apunte, C# Etiquetas:
  1. julio 1, 2015 en 9:58 am

    Usted es mi nuevo heroe, me ha salvado la vida enseñandome claramente el uso de los fileinfo. Gracias compañero.

  1. mayo 8, 2010 en 1:28 pm

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s