开发者

Check if a file/directory exists: is there a better way?

开发者 https://www.devze.com 2022-12-25 19:05 出处:网络
I find myself doing this a lot just to ensure the filename is not in use. Is there a better way? 开发者_运维问答

I find myself doing this a lot just to ensure the filename is not in use. Is there a better way?

开发者_运维问答
Directory.Exists(name) || File.Exists(name)


Sure :)

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


Note that the fact that you are using Exists() to check for file or directory name in use is subject to race conditions.

At any point after your Exists() test has passed, something could have created a file with that name before your code reaches the point where you create a file, for example.

(I'm assuming it is an exceptional condition for the file to already exist).

It is more reliable to simply to open the file, specifying an appropriate FileShare parameter.

Example:

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

So simply handling the IOException on failure may result in simpler code less prone to race conditions, because now:

  • If something else has already created the file, FileMode.CreateNew will cause an IOException to be thrown
  • If your open and create succeeds, because of FileShare.None, no other process can access the file until you close it.

Unfortunately, it is not possible to check whether a file is currently in use, and not throw an exception, without some ugly 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);
    }

And this fast check is also prone to race conditions, unless you return the file handle from it, and pass that to the relevant FileStream constructor.


I think that's the only way. I generally have a "FileManager" class which have static methods encapsulating I/O methods including the ones you indicated and then use that "FileManager" across all the applications as a library.


My way of checking this is using the FileSystemInfo, here is my code:

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

return info.Exists;


You can use following function:

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


Check if a directory Exists

string root = @"C:\Temp";        
// If directory does not exist, don't even try   
if (Directory.Exists(root))  
{  
    Directory.Delete(root);  
}  

Use the File.exists method in C# to check if a file exits in C# or not. Firstly, check whether the file is present in the current directory.

if (File.Exists("MyFile.txt")) {
   Console.WriteLine("The file exists.");
}

After that check whether the file exist in a directory or not

if (File.Exists(@"D:\myfile.txt")) {
   Console.WriteLine("The file exists.");
}


Another way to check if file exist.

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

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


How about checking whether FileAttributes == -1?

public static bool PathExists(this string path) {
    DirectoryInfo dirInfo = null;
    try { dirInfo = new DirectoryInfo(path.TrimEnd(Path.DirectorySeparatorChar)); }
    catch { }
    if (dirInfo == null || dirInfo.Attributes == (FileAttributes)(-1))
        return false;
    return true;
}


bool FileOrDirectoryExists(string path)
{
    try
    {
        File.GetAttributes(_source);
    }
    catch (FileNotFoundException)
    {
        return false;
    }
    return true;
}
0

精彩评论

暂无评论...
验证码 换一张
取 消