Question

Souvent, je me retrouve à interagir avec les fichiers d’une certaine manière, mais après avoir écrit le code, je ne sais toujours pas à quel point il est en réalité. Le problème est que je ne suis pas tout à fait sûr de savoir comment les opérations liées aux fichiers peuvent échouer et, par conséquent, la meilleure façon de gérer les expections.

La solution la plus simple semble être de détecter les IOExceptions levées par le code et de donner à l'utilisateur un "fichier inaccessible". message d’erreur mais est-il possible d’obtenir un peu plus précis des messages d’erreur. Existe-t-il un moyen de déterminer la différence entre de telles erreurs, par exemple un fichier verrouillé par un autre programme et des données illisibles en raison d’une erreur matérielle?

Étant donné le code C # suivant, comment géreriez-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();
   }
}
Était-ce utile?

La solution

  

... mais est-il possible d'obtenir un peu plus de messages d'erreur plus détaillés.

Oui. Allez-y et attrapez IOException et utilisez la méthode Exception.ToString () 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 voulez créer votre propre exception, vous devez vous rappeler de brancher cette chaîne dans le constructeur de Exception , comme :

lève une nouvelle exception FileNotFoundException ("Fichier introuvable");

Par ailleurs, conformément à l’article Scott Dorman , utilisez cette instruction à l'aide de . Ce qu'il faut remarquer, cependant, c'est que l'instruction utilisant ne intercepte pas , ce qui devrait être ainsi. Votre test pour voir si le fichier existe, par exemple, introduira une condition de concurrence critique qui pourrait être plutôt vexant . Cela ne vous fait vraiment aucun bien de l'avoir ici. 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. Utilisez avec
2, encapsulez l'instruction using ou la fonction using dans un try / catch qui catch es IOException
3. Utilisez Exception.ToString () dans votre 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 lancement pour vous.

Autres conseils

La première chose que vous devriez 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());
   }
}

Ceci se chargera d'appeler Close and Dispose pour vous et l'enveloppera dans un bloc try / finally afin que le code compilé actuel ressemble à ceci:

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 ici est que vous vous assurez que le flux est fermé même en cas d'exception.

En ce qui concerne la gestion plus explicite des exceptions, cela dépend vraiment de ce que vous voulez faire. Dans votre exemple, vous testez explicitement si le fichier existe et créez une exception FileNotFoundException qui peut suffire à vos utilisateurs, mais pas nécessairement.

  • Ignorer le fichier.Exists (); soit le gérer ailleurs, soit laisser CreateText () / OpenText () le lever.
  • 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 ce qui a été fait 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 dire ce qui ne va pas.

Je ne vois pas l'intérêt de vérifier l'existence d'un fichier et de lancer une exception FileNotFoundException sans message. La structure lancera l’exception FileNotFoundException elle-même, avec un message.

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

Je ferais ceci à peu près comme suit, intercepterais toute exception en dehors de la méthode et afficherait le message de l'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;
}

J'utiliserais l'instruction using pour simplifier la fermeture du fichier. Voir MSDN le C # à l'aide de l'instruction

.

À partir 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);
     }
  }

Ce n’est peut-être pas ce que vous recherchez, mais revoyez le type de traitement que vous utilisez pour la gestion des exceptions. Au premier abord, la gestion des exceptions ne doit pas être traitée comme "conviviale", du moins tant que vous pensez à un programmeur en tant qu'utilisateur.

Pour résumer, l'article suivant http://goit-postal.blogspot.com/2007/03/brief-introduction-to-exception.html .

Je voudrais essayer de vérifier le fichier. Existe avant d'appeler votre lecture / écriture et de répondre à l'utilisateur là-bas, au lieu de créer le temps système nécessaire pour générer une erreur et la récupérer plus tard, car la vérification est si facile à effectuer. Je comprends la nécessité de générer des erreurs, mais dans ce cas particulier, un simple contrôle à mon avis serait une meilleure solution. Ce que je veux dire, c’est d’ajouter une méthode supplémentaire pour vérifier si le fichier existe.

De plus, si vous vérifiez au préalable si le fichier existe, vous savez que quelque chose d'autre le bloque si vous ne pouvez pas y écrire. De plus, vous pouvez intercepter plusieurs exceptions, le premier à comparer sera intercepté - mais vous le savez probablement ...

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top