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)
Sûr :)
internal static bool FileOrDirectoryExists(string name)
{
return (Directory.Exists(name) || File.Exists(name));
}
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:
FileMode.CreateNew
provoquera le lancement d'un IOException
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é.
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.
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;
Une autre façon de vérifier si un fichier existe.
FileInfo file = new FileInfo("file.txt");
if (file.Exists)
{
// TO DO
}
Vous pouvez utiliser la fonction suivante:
[DllImport("shlwapi", EntryPoint = "PathFileExists", CharSet = CharSet.Unicode)]
public static extern bool PathExists(string path);