2010-04-03 7 views
38

Je me retrouve souvent à faire cela juste pour m'assurer que le nom de fichier n'est pas utilisé. Y a-t-il un meilleur moyen?Vérifiez si un fichier/répertoire existe: existe-t-il un meilleur moyen?

Directory.Exists(name) || File.Exists(name) 
+1

Et ce qui est mal à cela? Comment peut-il être plus facile ou plus propre? –

+0

Je le fais partout ... c'est moche. Habituellement, je ne vous inquiétez pas de la précédence, mais cela pourrait arriver –

+0

Pourquoi avez-vous besoin de ces 2 vérifications? Pourquoi n'utilisez-vous pas simplement File.Exists (nom)? – Egor4eg

Répondre

51

Bien sûr :)

internal static bool FileOrDirectoryExists(string name) 
{ 
    return (Directory.Exists(name) || File.Exists(name)); 
} 
+1

Méthode d'extension pour la classe Path? "Effectue des opérations sur les instances String contenant des informations sur le chemin du fichier ou du répertoire." – si618

+0

Si. demi bonne idée pour l'avoir dans une instance de chaîne. son vraiment à mauvais .NET ne permet pas d'étendre une classe statique :( –

+0

quelqu'un remarquez; erreur attendue? .xD 2014ppl d'ici, mais toujours merci @PaulG – Elegiac

4

Je pense que c'est la seule façon. J'ai généralement une classe "FileManager" qui possède des méthodes statiques encapsulant les méthodes d'E/S, y compris celles que vous avez indiquées, puis utilise ce "FileManager" dans toutes les applications en tant que bibliothèque.

5

Une autre façon de vérifier si le fichier existe.

FileInfo file = new FileInfo("file.txt"); 

if (file.Exists) 
{ 
    // TO DO 
} 
+0

Je doute que je descende voter pour cette réponse? – Anonymous

+0

Examinez les étiquettes avant de poster une réponse – lsalamon

+5

Le tag est C#, .NET et le fichier. Il s'agit d'un code C# et il peut donner le résultat désiré. tput. – Anonymous

29

Notez que le fait que vous utilisez exists() pour vérifier le nom du fichier ou un répertoire utilisé est soumis à des conditions course.

À tout moment après que votre Exists() test est passé, quelque chose aurait pu créer un fichier portant ce nom avant que votre code n'atteigne le point où vous créez un fichier, par exemple.

(Je suppose que c'est une condition exceptionnelle pour que le fichier existe déjà).

Il est plus fiable d'ouvrir simplement le fichier en spécifiant un paramètre FileShare approprié.

Exemple:

using System; 
using System.IO; 

static class FileNameInUse 
{ 
    static void Main(string[] args) 
    { 
     string path = args[0]; 
     using (var stream = File.Open(path, FileMode.CreateNew, FileAccess.Write, FileShare.None)) 
     { 
      // Write to file 
     } 
    } 
} 

Donc manipulation simplement le IOException en cas d'échec peut entraîner un code plus simple moins sujette à des conditions de race, parce que maintenant:

  • Si quelque chose a d'autre déjà créé le fichier , FileMode.CreateNew provoque un IOException être lancé
  • Si votre ouvrir et créer réussit, à cause de FileShare.None, aucun autre processus ne peut accéder au fichier tant que vous ne le fermez pas.

Malheureusement, il est impossible de vérifier si un fichier est actuellement utilisé, et ne pas jeter une exception, sans une vilaine P/Invoke:

bool IsFileInUse(string fileName) 
    { 
      IntPtr hFile = Win32.CreateFile(fileName, Win32.FILE_READ_DATA, 0, IntPtr.Zero, Win32.OPEN_EXISTING, Win32.FILE_ATTRIBUTE_NORMAL, IntPtr.Zero); 
      if (hFile.ToInt32() == Win32.INVALID_HANDLE_VALUE) 
       return true; 

      Win32.CloseHandle(hFile); 
      return false; 
    } 

    class Win32 
    { 
     const uint FILE_READ_DATA = 0x0001; 
     const uint FILE_SHARE_NONE = 0x00000000; 
     const uint FILE_ATTRIBUTE_NORMAL = 0x00000080; 
     const uint OPEN_EXISTING = 3; 
     const int INVALID_HANDLE_VALUE = -1; 

     [DllImport("kernel32.dll", SetLastError=true)] 
     internal static extern IntPtr CreateFile(string lpFileName, 
               uint dwDesiredAccess, 
               uint dwShareMode, 
               IntPtr lpSecurityAttributes, 
               uint dwCreationDisposition, 
               uint dwFlagsAndAttributes, 
               IntPtr hTemplateFile); 

     [DllImport("kernel32.dll")] 
     internal static extern bool CloseHandle(IntPtr hObject); 
    } 

Et cette vérification rapide est également est vulnérable aux conditions de concurrence, sauf si vous lui renvoyez le handle de fichier et le transmettez au constructeur FileStream correspondant.

+2

Pour une raison quelconque, les gens ne semblent jamais être reconnus pour avoir résolu le problème, seulement pour avoir répondu à la question. +1 pour répondre à la question qui aurait dû être posée. –

+0

+1. @Ben Voigt: Eh bien, il n'y a aucun moyen pour quiconque de connaître le problème depuis que je l'ai spécifié MAIS ma question est ce que je voulais savoir. J'utilise actuellement .Exist pour vérifier si mon application a créé un dossier temporaire (qu'il recherche un dossier inexistant et en crée un, puis en passant le nom). Je pourrais juste essayer {Directory.Delete()} attraper mais je préfère exister pour convaincre. En aucun cas, autre chose que mon application devrait supprimer le dossier. Le dossier est renommé une fois réussi. Donc Leon n'a pas vraiment résolu mon problème. –

+1

@Ben Voigt: en fait j'avais tort. Dans ce cas j'utilise Directory.delete mais quand je crée le répertoire j'utilise cette ligne pour vérifier si elle existe alors j'utilise Directory.CreateDirectory ou file.open avec le nom de fichier de retour. J'utilise la fonction pour générer le nom unique dans un format spécifique. –

2

Ma façon de vérifier ce utilise le FileSystemInfo, voici mon code:

FileSystemInfo info = 
    File.GetAttributes(data.Path).HasFlag(FileAttributes.Directory) ? 
    new DirectoryInfo(data.Path) : (FileSystemInfo)new FileInfo(data.Path); 

return info.Exists; 
+1

File.GetAttributes lève une exception System.IO.FileNotFoundException si aucun fichier ou répertoire n'existe –

Questions connexes