Question Comment gérer correctement les exceptions lors de l'exécution du fichier io


Souvent, je suis en train d'interagir avec des fichiers mais après avoir écrit le code, je ne sais toujours pas ce que c'est. Le problème est que je ne suis pas tout à fait sûr de la manière dont les opérations liées aux fichiers peuvent échouer et, par conséquent, du meilleur moyen de gérer les expulsions.

La solution simple semblerait être juste pour attraper les exceptions IOExceptées par le code et donner à l'utilisateur un message d'erreur "Inaccessible file" mais est-il possible d'obtenir des messages d'erreur un peu plus précis. Est-il possible de déterminer la différence entre des erreurs telles qu'un fichier verrouillé par un autre programme et des données illisibles en raison d'une erreur matérielle?

Compte tenu du code C # suivant, comment gérez-vous les erreurs de manière conviviale (aussi informative que possible)?

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();
   }
}

14
2017-09-17 19:36


origine


Réponses:


... mais est-il possible d'obtenir des messages d'erreur un peu plus précis.

Oui. Aller de l'avant et attraper IOException, et utilisez le Exception.ToString() méthode pour obtenir un message d'erreur relativement pertinent à afficher. Notez que les exceptions générées par le .NET Framework fourniront ces chaînes utiles, mais si vous prévoyez de créer votre propre exception, vous devez vous rappeler de connecter cette chaîne au Exceptionle constructeur, comme:

throw new FileNotFoundException("File not found");

Aussi, absolument, selon Scott Dorman, Utiliser ça using déclaration. La chose à noter, cependant, est que le using déclaration ne fait pas réellement catch n'importe quoi, c'est comme ça que ça devrait être. Votre test pour voir si le fichier existe, par exemple, introduira une condition de course qui peut être plutôt contrariant. Cela ne vous fait pas vraiment du bien de l'avoir là-dedans. Donc, maintenant, pour le lecteur, nous avons:

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

En bref, pour les opérations de base sur les fichiers:
1. utiliser using
2, enroulez l'instruction ou la fonction using dans un try/catch cette catches IOException
3. utiliser Exception.ToString() dans ton catch pour obtenir un message d'erreur utile
4. N'essayez pas de détecter vous-même des problèmes de fichiers exceptionnels. Laissez .NET faire le lancer pour vous.


12
2017-09-18 07:03



La première chose que vous devez changer est vos appels à StreamWriter et StreamReader pour les envelopper dans une instruction using, comme ceci:

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

Cela se chargera d'appeler Close et Dispose pour vous et l'enveloppera dans un bloc try / finally afin que le code compilé se présente comme suit:

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();
}

L'avantage est que vous vous assurez que le flux est fermé même si une exception se produit.

En ce qui concerne toute gestion des exceptions plus explicite, cela dépend vraiment de ce que vous voulez. Dans votre exemple, vous testez explicitement l'existence du fichier et lancez une exception FileNotFoundException qui peut suffire à vos utilisateurs, mais ce n'est peut-être pas le cas.


7
2017-09-17 19:43



  • Ignorez File.Exists (); soit le gérer ailleurs ou laisser CreateText () / OpenText () le déclencher.
  • L'utilisateur final ne se soucie généralement que s'il réussit ou non. Si cela échoue, dites-le simplement, il ne veut pas de détails.

Je n'ai pas trouvé de moyen intégré pour obtenir des détails sur quoi et pourquoi quelque chose a échoué dans .NET, mais si vous devenez natif avec CreateFile, vous avez des milliers de codes d'erreur qui peuvent vous indiquer ce qui a mal tourné.


1
2017-09-17 19:49



Je ne vois pas l'intérêt de vérifier l'existence d'un fichier et de lancer une exception FileNotFoundException sans message. Le framework va lancer l'exception FileNotFoundException avec un message.

Un autre problème avec votre exemple est que vous devez utiliser le modèle try / finally ou l'instruction using pour vous assurer que vos classes jetables sont correctement éliminées, même en cas d'exception.

Je ferais ceci quelque chose comme ceci, attraper n'importe quelle exception en dehors de la méthode et afficher le message d'exception:

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;
}

1
2017-09-17 19:52



Je voudrais utiliser l'instruction using pour simplifier la fermeture du fichier. Voir MSDN l'instruction C # utilisant

De 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);
     }
  }

0
2017-09-17 19:49



Peut-être que ce n'est pas ce que vous recherchez, mais reconsidérez le type de gestion des exceptions. Au début, la gestion des exceptions ne devrait pas être considérée comme "conviviale", du moins tant que vous considérez un programmeur comme un utilisateur.

Un résumé pour cela peut être l'article suivant http://goit-postal.blogspot.com/2007/03/brief-introduction-to-exception.html .


0
2017-09-17 19:55



Je voudrais essayer de vérifier le fichier.Existe avant d'appeler votre lecture / écriture et de répondre à l'utilisateur, au lieu de créer une erreur et de l'attraper plus tard car la vérification est si facile à faire. Je comprends la nécessité de soulever des erreurs, mais dans ce cas particulier, une simple vérification à mon avis serait une meilleure solution. Ce que je veux dire, c'est ajouter une méthode supplémentaire pour vérifier si le fichier existe.

Aussi, si vous vérifiez au préalable si le fichier se termine, vous savez que quelque chose le bloque si vous ne pouvez pas y écrire. Aussi, vous pouvez attraper de multiples exceptions, la première à correspondre sera interceptée - mais vous le savez probablement ...


-2
2017-09-17 19:38