Pregunta

A menudo me encuentro interactuando con archivos de alguna manera, pero después de escribir el código siempre no estoy seguro de qué tan robusto es en realidad.El problema es que no estoy del todo seguro de cómo pueden fallar las operaciones relacionadas con archivos y, por lo tanto, cuál es la mejor manera de manejar las expectativas.

La solución simple parecería ser simplemente detectar cualquier IOException lanzada por el código y darle al usuario un mensaje de error de "Archivo inaccesible", pero es posible obtener mensajes de error un poco más detallados.¿Existe alguna manera de determinar la diferencia entre errores como que otro programa bloquee un archivo y que los datos no se puedan leer debido a un error de hardware?

Dado el siguiente código C#, ¿cómo manejaría los errores de una manera fácil de usar (lo más informativa posible)?

public class IO
{
   public List<string> ReadFile(string path)
   {
      FileInfo file = new FileInfo(path);

      if (!file.Exists)
      {
         throw new FileNotFoundException();
      }

      StreamReader reader = file.OpenText();
      List<string> text = new List<string>();

      while (!reader.EndOfStream)
      {
         text.Add(reader.ReadLine());
      }

      reader.Close();
      reader.Dispose();
      return text;
   }

   public void WriteFile(List<string> text, string path)
   {
      FileInfo file = new FileInfo(path);

      if (!file.Exists)
      {
         throw new FileNotFoundException();
      }

      StreamWriter writer = file.CreateText();

      foreach(string line in text)
      {
         writer.WriteLine(line);
      }

      writer.Flush();
      writer.Close();
      writer.Dispose();
   }
}
¿Fue útil?

Solución

...pero ¿es posible recibir mensajes de error un poco más detallados?

Sí.Adelante y atrapa IOException, y utilizar el Exception.ToString() método para obtener un mensaje de error relativamente relevante para mostrar.Tenga en cuenta que las excepciones generadas por .NET Framework proporcionarán estas cadenas útiles, pero si va a generar su propia excepción, debe recordar insertar esa cadena en el Exceptionel constructor, como:

throw new FileNotFoundException("File not found");

Además, absolutamente, según Scott Dorman, usa eso using declaración.Lo que hay que notar, sin embargo, es que el using la declaración en realidad no catch cualquier cosa, que es como debe ser.Su prueba para ver si el archivo existe, por ejemplo, introducirá una condición de carrera que puede ser bastante irritante.Realmente no te sirve de nada tenerlo ahí.Entonces, ahora, para el lector tenemos:

try {  
    using (StreamReader reader = file.OpenText()) {  
        // Your processing code here  
    }  
} catch (IOException e) {  
    UI.AlertUserSomehow(e.ToString());  
}

En resumen, para operaciones básicas con archivos:
1.Usar using
2. Envuelva la declaración o función de uso en un try/catch eso catches IOException
3.Usar Exception.ToString() en tus catch para obtener un mensaje de error útil
4.No intente detectar usted mismo problemas de archivos excepcionales.Deje que .NET haga el trabajo por usted.

Otros consejos

Lo primero que debes cambiar son tus llamadas a StreamWriter y StreamReader para envolverlas en una declaración de uso, como esta:

using (StreamReader reader = file.OpenText())
{
   List<string> text = new List<string>();
   while (!reader.EndOfStream)
   {
      text.Add(reader.ReadLine());
   }
}

Esto se encargará de llamar a Close y Dispose por usted y, de hecho, lo envolverá en un bloque try/finally para que el código compilado real se vea así:

StreamReader reader = file.OpenText();
try
{
   List<string> text = new List<string>();
   while (!reader.EndOfStream)
   {
      text.Add(reader.ReadLine());
   }
}
finally
{
   if (reader != null)
      ((IDisposable)reader).Dispose();
}

El beneficio aquí es que garantiza que la transmisión se cierre incluso si ocurre una excepción.

En cuanto a un manejo de excepciones más explícito, realmente depende de lo que quieras que suceda.En su ejemplo, prueba explícitamente si el archivo existe y lanza una excepción FileNotFoundException que puede ser suficiente para sus usuarios, pero puede que no.

  • Omita el File.Exists();manejarlo en otro lugar o dejar que CreateText()/OpenText() lo genere.
  • Al usuario final normalmente sólo le importa si tiene éxito o no.Si falla, díselo, no quiere detalles.

No he encontrado una forma integrada de obtener detalles sobre qué y por qué algo falló en .NET, pero si utiliza CreateFile de forma nativa, tendrá miles de códigos de error que pueden indicarle qué salió mal.

No veo el sentido de verificar la existencia de un archivo y generar una FileNotFoundException sin ningún mensaje.El marco generará la propia FileNotFoundException, con un mensaje.

Otro problema con su ejemplo es que debería usar el patrón try/finally o la declaración de uso para garantizar que sus clases desechables se eliminen correctamente incluso cuando haya una excepción.

Haría algo parecido a lo siguiente, detectaría cualquier excepción fuera del método y mostraría el mensaje de la excepción:

public IList<string> ReadFile(string path)
{
    List<string> text = new List<string>();
    using(StreamReader reader = new StreamReader(path))
    {
      while (!reader.EndOfStream)      
      {         
         text.Add(reader.ReadLine());      
      }
    }
    return text;
}

Usaría la declaración de uso para simplificar el cierre del archivo.Ver MSDN la declaración de uso de C#

Desde MSDN:

  using (TextWriter w = File.CreateText("log.txt")) {
     w.WriteLine("This is line one");
     w.WriteLine("This is line two");
  }
  using (TextReader r = File.OpenText("log.txt")) {
     string s;
     while ((s = r.ReadLine()) != null) {
        Console.WriteLine(s);
     }
  }

Quizás esto no sea lo que está buscando, pero reconsidere el tipo de manejo de excepciones que está utilizando.Al principio, el manejo de excepciones no debe considerarse "fácil de usar", al menos mientras se piense en un programador como en un usuario.

Un resumen de esto puede ser el siguiente artículo. http://goit-postal.blogspot.com/2007/03/brief-introduction-to-exception.html .

Intentaría verificar el archivo. Existe antes de llamar a lectura/escritura y responder al usuario allí, en lugar de crear la sobrecarga de generar un error y detectarlo más tarde, ya que la verificación es muy fácil de realizar.Entiendo la necesidad de generar errores, pero en este caso particular, una simple verificación en mi humilde opinión sería una mejor solución.Lo que quiero decir es agregar un método más para verificar si el archivo existe.

Además, si comprueba de antemano si el archivo existe, sabrá que algo más lo está bloqueando si no puede escribir en él.También puede detectar múltiples excepciones; la primera que coincida será detectada, pero probablemente sepa esto...

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top