.NET. Как проверить, является ли путь файлом, а не каталогом?

У меня есть путь, и мне нужно определить, является ли он каталогом или файлом.

Это лучший способ определить, является ли путь файлом?

string file = @"C:\Test\foo.txt";

bool isFile = !System.IO.Directory.Exists(file) && 
                         System.IO.File.Exists(file);

Для каталога я бы отменил логику.

string directory = @"C:\Test";

bool isDirectory = System.IO.Directory.Exists(directory) && 
                            !System.IO.File.Exists(directory);

Если оба не существуют, то я не пойду ни на одну ветвь. Поэтому предположим, что они оба существуют.

Ответ 1

Использование:

System.IO.File.GetAttributes(string path)

и проверьте, содержит ли возвращаемый результат FileAttributes значение FileAttributes.Directory:

bool isDir = (File.GetAttributes(path) & FileAttributes.Directory)
                 == FileAttributes.Directory;

Ответ 2

Я думаю, что это самый простой способ, когда вам нужны только две проверки:

string file = @"C:\tmp";
if (System.IO.Directory.Exists(file))
{
    // do stuff when file is an existing directory
}
else if (System.IO.File.Exists(file))
{
    // do stuff when file is an existing file
}

Ответ 3

Вы можете сделать это с помощью некоторого кода взаимодействия:

    [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
    [return: MarshalAsAttribute(UnmanagedType.Bool)]
    public static extern bool PathIsDirectory([MarshalAsAttribute(UnmanagedType.LPWStr), In] string pszPath);

Чтобы прояснить некоторые комментарии...

Внедрение неуправляемого кода в этом уже не является наследованием опасным, чем любые другие вызовы, связанные с файлом или I/O в .NET, поскольку они ультиматулируют все вызовы в неуправляемый код.

Это один вызов функции с использованием строки. Вы не вводите новые типы данных и/или использование памяти, вызывая эту функцию. Да, вам нужно полагаться на неуправляемый код для правильной очистки, но в конечном итоге вы зависите от большинства вызовов, связанных с I/O.

Для справки, вот код в File.GetAttributes(путь строки) от Reflector:

public static FileAttributes GetAttributes(string path)
{
    string fullPathInternal = Path.GetFullPathInternal(path);
    new FileIOPermission(FileIOPermissionAccess.Read, new string[] { fullPathInternal }, false, false).Demand();
    Win32Native.WIN32_FILE_ATTRIBUTE_DATA data = new Win32Native.WIN32_FILE_ATTRIBUTE_DATA();
    int errorCode = FillAttributeInfo(fullPathInternal, ref data, false, true);
    if (errorCode != 0)
    {
        __Error.WinIOError(errorCode, fullPathInternal);
    }
    return (FileAttributes) data.fileAttributes;
}

Как вы можете видеть, он также вызывает неуправляемый код для извлечения атрибутов файла, поэтому аргументы в отношении введения неуправляемого кода являются опасными. Аналогичным образом, аргумент о полном пребывании в управляемом коде. Для этого не существует управляемой реализации кода. Даже вызывая File.GetAttributes(), поскольку другие ответы предлагают иметь те же "проблемы" для вызова неперечисленного кода, и я считаю, что это более надежный метод для определения того, является ли путь каталогом.

Изменить. Ответьте на комментарий @Christian K о CAS. Я считаю, что единственная причина, по которой GetAttributes делает требование безопасности, заключается в том, что ему нужно прочитать свойства файла, чтобы он хотел убедиться, что у вызывающего кода есть разрешение на это. Это не то же самое, что основные проверки ОС (если они есть). Вы всегда можете создать функцию обертки вокруг вызова P/Invoke в PathIsDirectory, который также требует определенных разрешений CAS, если это необходимо.

Ответ 4

Предполагая, что каталог существует...

bool isDir = (File.GetAttributes(path) & FileAttributes.Directory)
                  == FileAttributes.Directory;

Ответ 5

Проверьте это:

/// <summary>
/// Returns true if the given file path is a folder.
/// </summary>
/// <param name="Path">File path</param>
/// <returns>True if a folder</returns>
public bool IsFolder(string path)
{
    return ((File.GetAttributes(path) & FileAttributes.Directory) == FileAttributes.Directory);
}

from http://www.jonasjohn.de/snippets/csharp/is-folder.htm

Ответ 6

Прочитайте атрибуты файла:

FileAttributes att = System.IO.File.GetAttributes(PATH_TO_FILE);

Проверьте флаг Directory.

Ответ 7

Учитывая, что конкретная строка пути не может представлять как каталог, так и файл, то следующее работает очень хорошо и открывает дверь для других операций.

bool isFile = new FileInfo(path).Exists;
bool isDir = new DirectoryInfo(path).Exists;

Если вы работаете с файловой системой, использование FileInfo и DirectoryInfo намного проще, чем использование строк.

Ответ 8

Хмм, похоже, что класс Filesjava.nio) действительно имеет статический метод isDirectory. Итак, я думаю, вы могли бы использовать следующее:

Path what = ...
boolean isDir = Files.isDirectory(what);