Проверьте, существует ли файл / каталог: есть ли лучший способ? - PullRequest
40 голосов
/ 03 апреля 2010

Я часто занимаюсь этим, чтобы убедиться, что имя файла не используется. Есть ли лучший способ?

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

Ответы [ 7 ]

56 голосов
/ 03 апреля 2010

Конечно:)

internal static bool FileOrDirectoryExists(string name)
{
   return (Directory.Exists(name) || File.Exists(name));
}
33 голосов
/ 05 апреля 2010

Обратите внимание, что тот факт, что вы используете Exists () для проверки имени файла или каталога при использовании , зависит от условий гонки.

В любой момент после того, как ваш Exists () тест пройден, что-то могло создать файл с таким именем до того, как ваш код достигнет точки, где вы создаете файл, например.

(я предполагаю, что это исключительное условие для того, чтобы файл уже существовал).

Надежнее просто открыть файл, указав соответствующий параметр FileShare.

Пример:

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

Таким образом, простая обработка IOException при сбое может привести к тому, что более простой код будет менее подвержен условиям гонки, потому что теперь:

  • Если что-то еще уже создало файл, FileMode.CreateNew вызовет выброс IOException
  • Если открытие и создание завершилось успешно из-за FileShare.None, никакой другой процесс не сможет получить доступ к файлу, пока вы не закроете его.

К сожалению, невозможно проверить, используется ли файл в данный момент , и не выдать исключение, без какого-либо уродливого 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);
    }

И эта быстрая проверка также подвержена условиям гонки, если вы не вернете из нее дескриптор файла и не передадите его соответствующему конструктору FileStream.

4 голосов
/ 03 апреля 2010

Я думаю, что это единственный способ. У меня обычно есть класс FileManager, в котором есть статические методы, инкапсулирующие методы ввода-вывода, включая те, которые вы указали, и затем использующие этот FileManager для всех приложений в качестве библиотеки.

2 голосов
/ 21 июня 2013

Мой способ проверить это с помощью FileSystemInfo , вот мой код:

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

return info.Exists;
2 голосов
/ 03 апреля 2010

Другой способ проверить, существует ли файл.

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

if (file.Exists)
{
    // TO DO
}
0 голосов
/ 24 июня 2019

Вы можете использовать следующую функцию:

[DllImport("shlwapi", EntryPoint = "PathFileExists", CharSet = CharSet.Unicode)]
public static extern bool PathExists(string path);
0 голосов
/ 03 сентября 2018
bool FileOrDirectoryExists(string path)
{
    try
    {
        File.GetAttributes(_source);
    }
    catch (FileNotFoundException)
    {
        return false;
    }
    return true;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...