web-dev-qa-db-fra.com

Vérifiez s'il existe un fichier / répertoire: existe-t-il une meilleure solution?

Je me retrouve souvent à faire cela juste pour m'assurer que le nom de fichier n'est pas utilisé. Y a-t-il une meilleure façon?

Directory.Exists(name) || File.Exists(name)
40
user34537

Sûr :)

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

Notez que le fait que vous utilisez Exists () pour vérifier le nom du fichier ou du répertoire en cours d'utilisation est soumis aux conditions de concurrence.

À tout moment après la réussite de votre test Exists (), quelque chose aurait pu créer un fichier avec ce nom avant que votre code 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
        }
    }
}

Ainsi, la simple gestion de IOException en cas d'échec peut entraîner un code plus simple moins sujet aux conditions de concurrence, car maintenant:

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

Malheureusement, il n'est pas possible de vérifier si un fichier est actuellement en cours d'utilisation, et de ne pas lever d'exception, sans un P/Invoke laid:

    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 sujette aux conditions de concurrence, à moins que vous n'en retourniez le descripteur de fichier et que vous le transmettiez au constructeur FileStream approprié.

34
Leon Breedt

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

4
Ashish Gupta

Ma façon de vérifier cela 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;
2

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

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

if (file.Exists)
{
    // TO DO
}
2
Anonymous

Vous pouvez utiliser la fonction suivante:

[DllImport("shlwapi", EntryPoint = "PathFileExists", CharSet = CharSet.Unicode)]
public static extern bool PathExists(string path);
0
TN.