Подтвердить что ты не робот

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

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

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

Ответ 1

Конечно:)

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

Ответ 2

Обратите внимание, что тот факт, что вы используете 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.

Ответ 3

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

Ответ 4

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

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

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

Ответ 5

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

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

return info.Exists;

Ответ 6

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

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

Ответ 7

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