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

Я обрабатываю TreeView каталогов и файлов. Пользователь может выбрать файл или каталог, а затем что-то с ним сделать. Это требует, чтобы у меня был метод, который выполняет разные действия в зависимости от выбора пользователя.

В настоящий момент я делаю что-то вроде этого, чтобы определить, является ли путь файлом или каталогом:

bool bIsFile = false;
bool bIsDirectory = false;

try
{
    string[] subfolders = Directory.GetDirectories(strFilePath);

    bIsDirectory = true;
    bIsFile = false;
}
catch(System.IO.IOException)
{
    bIsFolder = false;
    bIsFile = true;
}

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


person SnAzBaZ    schedule 08.09.2009    source источник
comment
Может ли кто-нибудь отредактировать заголовок вопроса, указав существующий файл / каталог? Все ответы относятся к пути к файлу / каталогу на диске.   -  person Jake Berger    schedule 04.06.2012
comment
@jberger, пожалуйста, обратитесь к моему ответу ниже. Я нашел способ сделать это для путей к файлам / папкам, которые могут существовать или не существовать.   -  person lhan    schedule 18.10.2012
comment
возможный дубликат .NET How чтобы проверить, является ли путь файлом, а не каталогом?   -  person nawfal    schedule 12.06.2013
comment
Как вы заполняете это древовидное представление? Как вы выберетесь из этого пути?   -  person Random832    schedule 22.12.2013


Ответы (21)


Из Как узнать, путь к файлу или каталог:

// get the file attributes for file or directory
FileAttributes attr = File.GetAttributes(@"c:\Temp");

//detect whether its a directory or file
if ((attr & FileAttributes.Directory) == FileAttributes.Directory)
    MessageBox.Show("Its a directory");
else
    MessageBox.Show("Its a file");

Обновление для .NET 4.0+

Согласно комментариям ниже, если вы используете .NET 4.0 или новее (и максимальная производительность не критична), вы можете написать код более чистым способом:

// get the file attributes for file or directory
FileAttributes attr = File.GetAttributes(@"c:\Temp");

if (attr.HasFlag(FileAttributes.Directory))
    MessageBox.Show("Its a directory");
else
    MessageBox.Show("Its a file");
person Quinn Wilson    schedule 08.09.2009
comment
+1 Это лучший подход и он значительно быстрее предложенного мною решения. - person Andrew Hare; 08.09.2009
comment
И мне кажется, что это официальный способ сделать это. Вперед! - person Pavel Donchev; 12.04.2012
comment
Если это не работает для несуществующих файлов / папок, не могли бы вы заключить код в блок try / catch и вернуть false для обоих (путь! = Файл && путь! = Папка)? Это действительно помогает мне решить мою проблему! - person mbm29414; 02.07.2012
comment
Может ли кто-нибудь объяснить, почему операторы if содержат attr & FileAttributes.Directory, а не только attr? Я не могу понять это: P - person Daan; 31.08.2012
comment
@ KeyMs92 Его побитовая математика. По сути, attr - это какое-то двоичное значение с одним битом, означающим, что это каталог. Поразрядный оператор and & вернет двоичное значение, в котором включены только биты, которые находятся на (1) в обоих операндах. В этом случае выполнение побитовой операции и с attr и значением FileAttributes.Directory вернет значение FileAttributes.Directory, если бит атрибута файла Справочника установлен. См. en.wikipedia.org/wiki/Bitwise_operation для лучшего объяснения. - person Kyle Trauberman; 31.08.2012
comment
@jberger Если путь не существует, то неясно, относится ли C:\Temp к каталогу с именем Temp или к файлу с именем Temp. Что должен делать код? - person ta.speot.is; 02.12.2012
comment
@Key: после .NET 4.0 вместо него можно использовать attr.HasFlag(FileAttributes.Directory). - person Şafak Gür; 15.05.2013
comment
@ AfakGür: Не делайте этого внутри петли, чувствительной ко времени. attr.HasFlag () работает чертовски медленно и использует Reflection для каждого вызова - person springy76; 17.05.2013
comment
@ springy76: это медленнее, чем побитовое сравнение (16 раз, согласно Уиллу), но если только он не находится в очень критичном по времени цикле , Я бы сказал, что использование HasFlag гораздо более выразительно и поэтому предпочтительнее, несмотря на его относительную медленность по сравнению с прямым побитовым сравнением. Как всегда, OP должен провести некоторые тесты, чтобы решить, следует ли избегать HasFlag - это микрооптимизация в его конкретном сценарии. - person Şafak Gür; 17.05.2013
comment
Сначала необходимо проверить строку пути на нулевое значение. Кроме того, перед проверкой атрибута можно использовать Directory.Exists (путь) или File.Exists (путь). - person Anthony; 28.08.2014
comment
Попробуй это! (после вставки в редакторе и переформатирования конечно;)) /// Returns true if the path is a dir, false if it's a file and null if it's neither or doesn't exist. public static bool? IsDirFile(this string path) { bool? result = null; if(Directory.Exists(path) || File.Exists(path)) { // get the file attributes for file or directory var fileAttr = File.GetAttributes(path); if (fileAttr.HasFlag(FileAttributes.Directory)) result = true; else result = false; } return result; } - person Mike Socha III; 31.03.2015
comment
Мне нравится вариант Майка. приведенное выше решение создает исключение. +1 - person Lee; 17.08.2016
comment
Версия Майка немного упрощена: public static bool? IsDirFile (строковый путь) {if (! Directory.Exists (путь) &&! File.Exists (путь)) return null; var fileAttr = File.GetAttributes (путь); return! fileAttr.HasFlag (FileAttributes.Directory); } - person nh43de; 29.09.2016
comment
Поразрядный метод можно сократить, сравнив результат с 0 (нулем). например if ((attr & FileAttributes.Directory) != 0) - person Thariq Nugrohotomo; 03.03.2017
comment
Может ли кто-нибудь объяснить, почему это правильный ответ, получивший огромное количество голосов, а Directory.Exists - нет? Directory.Exists в основном делает то же самое, насколько я могу понять, только более надежным способом. Я думаю, что это один пост, в котором такой ответ на самом деле немного вводит в заблуждение. - person Rich N; 12.07.2017
comment
@MikeSochaIII - при каких обстоятельствах File.GetAttributes найдет полезную информацию, отличную от той, которую вы уже узнали из Directory.Exists и File.Exists ?? AFAIK, вы закончили, после того, как вы проверили существование. См. Комментарий к коду Дастина Таунсенда в разделе ответ llamaoo7. - person ToolmakerSteve; 02.04.2018
comment
Почему бы нам не использовать это: LogFileName.Contains (@ \) {}.? чтобы проверить каталог или файл .... - person SaddamBinSyed; 22.05.2018
comment
@SaddamBinSyed - ужасная идея использовать разделитель каталогов для структуры пути. Это похоже на то, как вы проверяете гражданский адрес через запятую или точку. - person Brian Ng; 01.03.2019
comment
Вероятно, следует отметить, что File.GetAttributes выдает исключение, если файл не существует ... Что не является хорошим методом проверки, относится ли путь к файлу или каталогу. - person Douglas Gaskell; 01.08.2019
comment
@RichN Вероятно, потому что это правильный способ сделать это в тех случаях, когда вы знаете, что путь существует (например, приложение с графическим интерфейсом, которое поддерживает перетаскивание - когда кто-то перетаскивает элемент файловой системы, вы знаете, что путь существует, потому что они должны были перетащите действительный элемент, но вам все равно нужно проверить, является ли то, что они перетаскивают, папкой или файлом) - person Herohtar; 27.11.2019
comment
@Herohtar Ты заставил меня снова взглянуть на это! Я все еще не уверен. Насколько я понимаю, Directory.Exists делает почти то же самое, что и выше. Он даже вызывает тот же внутренний метод FillAttributeInfo. Основное отличие состоит в том, что он возвращает false, если путь не существует, а не генерирует исключения. Итак, если вы знаете, что путь существует, я думаю, вы можете использовать либо принятый ответ, либо Directory.Exists (и / или File.Exists), и последний мне кажется более чистым? Я думаю, если вы ХОТИТЕ его выбросить, если путь не существует, принятый ответ может быть лучше. - person Rich N; 27.11.2019
comment
Методы @RichN File.GetAttributes и Exists в конечном итоге вызывают FillAttributeInfo, но оба метода Exists делают дополнительные вещи, которые делают их немного медленнее, что может быть рассмотрено, если вы выполняете много операций. В зависимости от того, что вы пытаетесь выяснить, вам также может потребоваться позвонить как File.Exists , так и Directory.Exists, чтобы получить необходимую информацию, а не просто позвонить в File.GetAttributes. - person Herohtar; 28.11.2019
comment
У меня следующий вопрос: если есть такой цикл: foreach (var item in files){ //files in folder FileAttributes attrib = File.GetAttributes(item.FullName);... Означает ли это, что для получения атрибутов каждого элемента в цикле выполняется чтение с диска? Спасибо - person lm.; 07.10.2020

Как насчет их использования?

File.Exists();
Directory.Exists();
person llamaoo7    schedule 08.09.2009
comment
Это также имеет то преимущество, что в отличие от File.GetAttributes(), исключение не создается на недопустимом пути. - person Deanna; 16.12.2011
comment
Я использую библиотеку Long Path из BCL bcl.codeplex.com/ в мой проект, поэтому нет возможности получить атрибуты файла, но вызов Exist - хороший обходной путь. - person Puterdo Borato; 27.02.2012
comment
@jberger Я ожидал, что он НЕ будет работать для путей к несуществующим файлам / папкам. File.Exists (c: \ temp \ nonexistant.txt) должен возвращать false, как и есть. - person michaelkoss; 04.06.2012
comment
@michaelkoss согласился, я не ожидаю, что этот ответ будет работать и на несуществующих путях. Однако в моем первом комментарии к вопросу я имел в виду, что вопрос следует обновить, чтобы указать, является ли путь для существующего или для любого ( несуществующий) путь. Однако я не знаю, что OP пытается получить, так что это не похоже на мое место. - person Jake Berger; 07.12.2012
comment
Если вас беспокоят несуществующие файлы / папки, попробуйте это public static bool? IsDirectory(string path){ if (Directory.Exists(path)) return true; // is a directory else if (File.Exists(path)) return false; // is a file else return null; // is a nothing } - person Dustin Townsend; 26.06.2014
comment
Более подробная информация об этом находится на msdn.microsoft.com/en-us/library/ - person Moji; 07.01.2015
comment
+1, потому что мне нравится это решение, но учитывайте его при удалении файла или каталога. Тогда у тебя не будет пути. - person Mitulát báti; 19.02.2016

Только с помощью этой строки вы можете получить, если путь является каталогом или файлом:

File.GetAttributes(data.Path).HasFlag(FileAttributes.Directory)
person Gerard Gilabert Canal    schedule 21.06.2013
comment
Имейте в виду, что для этого вам понадобится как минимум .NET 4.0. Также это взорвется, если путь не является допустимым путем. - person nawfal; 21.06.2013
comment
Используйте объект FileInfo, чтобы проверить, существует ли путь: FileInfo pFinfo = new FileInfo (FList [0]); if (pFinfo.Exists) {if (File.GetAttributes (FList [0]). HasFlag (FileAttributes.Directory)) {}}. Этот мне подходит. - person Michael Stimson; 09.05.2016
comment
Если вы уже создали объект FileInfo и используете свойство Exists экземпляра, почему бы не получить доступ к его свойству Attributes вместо использования статического метода File.GetAttributes ()? - person dynamichael; 04.06.2018

Вот мой:

    bool IsPathDirectory(string path)
    {
        if (path == null) throw new ArgumentNullException("path");
        path = path.Trim();

        if (Directory.Exists(path)) 
            return true;

        if (File.Exists(path)) 
            return false;

        // neither file nor directory exists. guess intention

        // if has trailing slash then it's a directory
        if (new[] {"\\", "/"}.Any(x => path.EndsWith(x)))
            return true; // ends with slash

        // if has extension then its a file; directory otherwise
        return string.IsNullOrWhiteSpace(Path.GetExtension(path));
    }

Это похоже на ответы других, но не совсем то же самое.

person Ronnie Overby    schedule 25.10.2013
comment
Технически вы должны использовать Path.DirectorySeparatorChar и Path.AltDirectorySeparatorChar - person drzaus; 02.02.2016
comment
Идея угадать намерение интересна. ИМХО лучше разделить на два метода. Первый метод выполняет тесты существования, возвращая логическое значение, допускающее значение NULL. Если вызывающий затем хочет часть предположения при нулевом результате от One, тогда вызовите метод 2, который выполняет предположение. - person ToolmakerSteve; 02.04.2018
comment
Я бы переписал это, чтобы вернуть кортеж независимо от того, угадал он или нет. - person Ronnie Overby; 03.04.2018
comment
если имеет расширение, то это файл - это неправда. Файл не обязательно должен иметь расширение (даже в Windows), а каталог может иметь расширение. Например, это может быть файл или каталог: C: \ New folder.log - person bytedev; 19.09.2018
comment
@bytedev Я знаю это, но в этот момент в функции код угадывает намерение. Об этом даже говорится в комментарии. У большинства файлов есть расширение. Большинство каталогов этого не делают. - person Ronnie Overby; 20.09.2018

Объединив предложения из других ответов, я понял, что придумал примерно то же, что и ответ Ронни Оверби. Вот несколько тестов, которые помогут вам подумать:

  1. папки могут иметь "расширения": C:\Temp\folder_with.dot
  2. файлы не могут заканчиваться разделителем каталогов (косая черта)
  3. Технически существует два разделителя каталогов, которые зависят от платформы, т.е. могут или не быть косой чертой (Path.DirectorySeparatorChar и Path.AltDirectorySeparatorChar).

Тесты (Linqpad)

var paths = new[] {
    // exists
    @"C:\Temp\dir_test\folder_is_a_dir",
    @"C:\Temp\dir_test\is_a_dir_trailing_slash\",
    @"C:\Temp\dir_test\existing_folder_with.ext",
    @"C:\Temp\dir_test\file_thats_not_a_dir",
    @"C:\Temp\dir_test\notadir.txt",
    // doesn't exist
    @"C:\Temp\dir_test\dne_folder_is_a_dir",
    @"C:\Temp\dir_test\dne_folder_trailing_slash\",
    @"C:\Temp\dir_test\non_existing_folder_with.ext",
    @"C:\Temp\dir_test\dne_file_thats_not_a_dir",
    @"C:\Temp\dir_test\dne_notadir.txt",        
};

foreach(var path in paths) {
    IsFolder(path/*, false*/).Dump(path);
}

Полученные результаты

C:\Temp\dir_test\folder_is_a_dir
  True 
C:\Temp\dir_test\is_a_dir_trailing_slash\
  True 
C:\Temp\dir_test\existing_folder_with.ext
  True 
C:\Temp\dir_test\file_thats_not_a_dir
  False 
C:\Temp\dir_test\notadir.txt
  False 
C:\Temp\dir_test\dne_folder_is_a_dir
  True 
C:\Temp\dir_test\dne_folder_trailing_slash\
  True 
C:\Temp\dir_test\non_existing_folder_with.ext
  False (this is the weird one)
C:\Temp\dir_test\dne_file_thats_not_a_dir
  True 
C:\Temp\dir_test\dne_notadir.txt
  False 

Метод

/// <summary>
/// Whether the <paramref name="path"/> is a folder (existing or not); 
/// optionally assume that if it doesn't "look like" a file then it's a directory.
/// </summary>
/// <param name="path">Path to check</param>
/// <param name="assumeDneLookAlike">If the <paramref name="path"/> doesn't exist, does it at least look like a directory name?  As in, it doesn't look like a file.</param>
/// <returns><c>True</c> if a folder/directory, <c>false</c> if not.</returns>
public static bool IsFolder(string path, bool assumeDneLookAlike = true)
{
    // https://stackoverflow.com/questions/1395205/better-way-to-check-if-path-is-a-file-or-a-directory
    // turns out to be about the same as https://stackoverflow.com/a/19596821/1037948

    // check in order of verisimilitude

    // exists or ends with a directory separator -- files cannot end with directory separator, right?
    if (Directory.Exists(path)
        // use system values rather than assume slashes
        || path.EndsWith("" + Path.DirectorySeparatorChar)
        || path.EndsWith("" + Path.AltDirectorySeparatorChar))
        return true;

    // if we know for sure that it's an actual file...
    if (File.Exists(path))
        return false;

    // if it has an extension it should be a file, so vice versa
    // although technically directories can have extensions...
    if (!Path.HasExtension(path) && assumeDneLookAlike)
        return true;

    // only works for existing files, kinda redundant with `.Exists` above
    //if( File.GetAttributes(path).HasFlag(FileAttributes.Directory) ) ...; 

    // no idea -- could return an 'indeterminate' value (nullable bool)
    // or assume that if we don't know then it's not a folder
    return false;
}
person drzaus    schedule 02.02.2016
comment
Path.DirectorySeparatorChar.ToString() вместо объединения строк с ""? - person Gone Coding; 26.08.2016
comment
@GoneCoding наверное; в то время я работал с кучей свойств, допускающих значение NULL, поэтому у меня появилась привычка конкатенировать с пустой строкой, а не беспокоиться о проверке на значение NULL. Вы также можете сделать new String(Path.DirectorySeparatorChar, 1), как это делает ToString, если хотите действительно оптимизировать. - person drzaus; 26.08.2016

В качестве альтернативы Directory.Exists () вы можете использовать метод File.GetAttributes () для получения атрибутов файла или каталога, чтобы вы могли создать вспомогательный метод, подобный этому:

private static bool IsDirectory(string path)
{
    System.IO.FileAttributes fa = System.IO.File.GetAttributes(path);
    return (fa & FileAttributes.Directory) != 0;
}

Вы также можете рассмотреть возможность добавления объекта в свойство tag элемента управления TreeView при заполнении элемента управления, который содержит дополнительные метаданные для элемента. Например, вы можете добавить объект FileInfo для файлов и объект DirectoryInfo для каталогов, а затем проверить тип элемента в свойстве тега, чтобы сохранить дополнительные системные вызовы для получения этих данных при нажатии на элемент.

person Michael A. McCloskey    schedule 08.09.2009
comment
чем это отличается от другого ответа - person Jake Berger; 31.05.2012
comment
Вместо этого ужасного блока логики попробуйте isDirectory = (fa & FileAttributes.Directory) != 0); - person Immortal Blue; 16.02.2013

Это было лучшее, что я мог придумать, учитывая поведение свойств Exists и Attributes:

using System.IO;

public static class FileSystemInfoExtensions
{
    /// <summary>
    /// Checks whether a FileInfo or DirectoryInfo object is a directory, or intended to be a directory.
    /// </summary>
    /// <param name="fileSystemInfo"></param>
    /// <returns></returns>
    public static bool IsDirectory(this FileSystemInfo fileSystemInfo)
    {
        if (fileSystemInfo == null)
        {
            return false;
        }

        if ((int)fileSystemInfo.Attributes != -1)
        {
            // if attributes are initialized check the directory flag
            return fileSystemInfo.Attributes.HasFlag(FileAttributes.Directory);
        }

        // If we get here the file probably doesn't exist yet.  The best we can do is 
        // try to judge intent.  Because directories can have extensions and files
        // can lack them, we can't rely on filename.
        // 
        // We can reasonably assume that if the path doesn't exist yet and 
        // FileSystemInfo is a DirectoryInfo, a directory is intended.  FileInfo can 
        // make a directory, but it would be a bizarre code path.

        return fileSystemInfo is DirectoryInfo;
    }
}

Вот как это проверяется:

    [TestMethod]
    public void IsDirectoryTest()
    {
        // non-existing file, FileAttributes not conclusive, rely on type of FileSystemInfo
        const string nonExistentFile = @"C:\TotallyFakeFile.exe";

        var nonExistentFileDirectoryInfo = new DirectoryInfo(nonExistentFile);
        Assert.IsTrue(nonExistentFileDirectoryInfo.IsDirectory());

        var nonExistentFileFileInfo = new FileInfo(nonExistentFile);
        Assert.IsFalse(nonExistentFileFileInfo.IsDirectory());

        // non-existing directory, FileAttributes not conclusive, rely on type of FileSystemInfo
        const string nonExistentDirectory = @"C:\FakeDirectory";

        var nonExistentDirectoryInfo = new DirectoryInfo(nonExistentDirectory);
        Assert.IsTrue(nonExistentDirectoryInfo.IsDirectory());

        var nonExistentFileInfo = new FileInfo(nonExistentDirectory);
        Assert.IsFalse(nonExistentFileInfo.IsDirectory());

        // Existing, rely on FileAttributes
        const string existingDirectory = @"C:\Windows";

        var existingDirectoryInfo = new DirectoryInfo(existingDirectory);
        Assert.IsTrue(existingDirectoryInfo.IsDirectory());

        var existingDirectoryFileInfo = new FileInfo(existingDirectory);
        Assert.IsTrue(existingDirectoryFileInfo.IsDirectory());

        // Existing, rely on FileAttributes
        const string existingFile = @"C:\Windows\notepad.exe";

        var existingFileDirectoryInfo = new DirectoryInfo(existingFile);
        Assert.IsFalse(existingFileDirectoryInfo.IsDirectory());

        var existingFileFileInfo = new FileInfo(existingFile);
        Assert.IsFalse(existingFileFileInfo.IsDirectory());
    }
person HAL9000    schedule 19.06.2013

Самый точный подход - использовать некоторый код взаимодействия из shlwapi.dll.

[DllImport(SHLWAPI, CharSet = CharSet.Unicode)]
[return: MarshalAsAttribute(UnmanagedType.Bool)]
[ResourceExposure(ResourceScope.None)]
internal static extern bool PathIsDirectory([MarshalAsAttribute(UnmanagedType.LPWStr), In] string pszPath);

Тогда вы бы назвали это так:

#region IsDirectory
/// <summary>
/// Verifies that a path is a valid directory.
/// </summary>
/// <param name="path">The path to verify.</param>
/// <returns><see langword="true"/> if the path is a valid directory; 
/// otherwise, <see langword="false"/>.</returns>
/// <exception cref="T:System.ArgumentNullException">
/// <para><paramref name="path"/> is <see langword="null"/>.</para>
/// </exception>
/// <exception cref="T:System.ArgumentException">
/// <para><paramref name="path"/> is <see cref="F:System.String.Empty">String.Empty</see>.</para>
/// </exception>
public static bool IsDirectory(string path)
{
    return PathIsDirectory(path);
}
person Scott Dorman    schedule 08.09.2009
comment
Уродливый. Я ненавижу Interop для выполнения этих простых задач. И это не портативный. и это уродливо. Я сказал, что это уродливо? :) - person Ignacio Soler Garcia; 14.11.2011
comment
@SoMoS Это может показаться некрасивым, но это все же самый точный подход. Да, это не портативное решение, но вопрос задавался не об этом. - person Scott Dorman; 15.11.2011
comment
Что ты имеешь в виду под точным? Он дает те же результаты, что и ответ Куинна Уилсона, и требует взаимодействия, что нарушает переносимость. Для меня это так же точно, как и другие решения, и имеет побочные эффекты, которых нет у других. - person Ignacio Soler Garcia; 17.11.2011
comment
Он не работает с несуществующими файлами или каталогами. - person Ray Cheng; 27.12.2014
comment
Для этого есть API Framework. Использование Interop - не лучший вариант. - person TomXP411; 26.02.2015
comment
Да, это работает, но это НЕ самое точное решение - не более чем использование существующей .NET Framework. Вместо этого вы берете 6 строк кода, чтобы заменить то, что можно сделать в одной строке с .NET Framework, и ограничиваете себя использованием только Windows, вместо того, чтобы оставлять открытой возможность переноса этого с помощью Mono Project. Никогда не используйте Interop, если .NET Framework предлагает более элегантное решение. - person Russ; 17.03.2015
comment
@ScottDorman - Опишите ситуацию, когда это более точно, чем управляемый метод System.IO.Directory.Exists. - person ToolmakerSteve; 02.04.2018
comment
@RufusL - как видно из других ответов, вы можете вызывать Directory.Exists и File.Exists. Если оба возвращают false, значит, вы знаете, что этого не существует. Без исключения. И без импорта каких-либо неуправляемых вызовов нижнего уровня. Это стало возможным с версии .NET 1.1 в 2003 году. - person ToolmakerSteve; 02.04.2018

Вот что мы используем:

using System;

using System.IO;

namespace crmachine.CommonClasses
{

  public static class CRMPath
  {

    public static bool IsDirectory(string path)
    {
      if (path == null)
      {
        throw new ArgumentNullException("path");
      }

      string reason;
      if (!IsValidPathString(path, out reason))
      {
        throw new ArgumentException(reason);
      }

      if (!(Directory.Exists(path) || File.Exists(path)))
      {
        throw new InvalidOperationException(string.Format("Could not find a part of the path '{0}'",path));
      }

      return (new System.IO.FileInfo(path).Attributes & FileAttributes.Directory) == FileAttributes.Directory;
    } 

    public static bool IsValidPathString(string pathStringToTest, out string reasonForError)
    {
      reasonForError = "";
      if (string.IsNullOrWhiteSpace(pathStringToTest))
      {
        reasonForError = "Path is Null or Whitespace.";
        return false;
      }
      if (pathStringToTest.Length > CRMConst.MAXPATH) // MAXPATH == 260
      {
        reasonForError = "Length of path exceeds MAXPATH.";
        return false;
      }
      if (PathContainsInvalidCharacters(pathStringToTest))
      {
        reasonForError = "Path contains invalid path characters.";
        return false;
      }
      if (pathStringToTest == ":")
      {
        reasonForError = "Path consists of only a volume designator.";
        return false;
      }
      if (pathStringToTest[0] == ':')
      {
        reasonForError = "Path begins with a volume designator.";
        return false;
      }

      if (pathStringToTest.Contains(":") && pathStringToTest.IndexOf(':') != 1)
      {
        reasonForError = "Path contains a volume designator that is not part of a drive label.";
        return false;
      }
      return true;
    }

    public static bool PathContainsInvalidCharacters(string path)
    {
      if (path == null)
      {
        throw new ArgumentNullException("path");
      }

      bool containedInvalidCharacters = false;

      for (int i = 0; i < path.Length; i++)
      {
        int n = path[i];
        if (
            (n == 0x22) || // "
            (n == 0x3c) || // <
            (n == 0x3e) || // >
            (n == 0x7c) || // |
            (n  < 0x20)    // the control characters
          )
        {
          containedInvalidCharacters = true;
        }
      }

      return containedInvalidCharacters;
    }


    public static bool FilenameContainsInvalidCharacters(string filename)
    {
      if (filename == null)
      {
        throw new ArgumentNullException("filename");
      }

      bool containedInvalidCharacters = false;

      for (int i = 0; i < filename.Length; i++)
      {
        int n = filename[i];
        if (
            (n == 0x22) || // "
            (n == 0x3c) || // <
            (n == 0x3e) || // >
            (n == 0x7c) || // |
            (n == 0x3a) || // : 
            (n == 0x2a) || // * 
            (n == 0x3f) || // ? 
            (n == 0x5c) || // \ 
            (n == 0x2f) || // /
            (n  < 0x20)    // the control characters
          )
        {
          containedInvalidCharacters = true;
        }
      }

      return containedInvalidCharacters;
    }

  }

}
person PMBottas    schedule 01.07.2012

Я столкнулся с этим, когда столкнулся с аналогичной проблемой, за исключением того, что мне нужно было проверить, указан ли путь к файлу или папке , когда этот файл или папка на самом деле может не существовать. Было несколько комментариев к ответам выше, в которых упоминалось, что они не будут работать для этого сценария. Я нашел решение (я использую VB.NET, но вы можете конвертировать, если вам нужно), которое, похоже, мне подходит:

Dim path As String = "myFakeFolder\ThisDoesNotExist\"
Dim bIsFolder As Boolean = (IO.Path.GetExtension(path) = "")
'returns True

Dim path As String = "myFakeFolder\ThisDoesNotExist\File.jpg"
Dim bIsFolder As Boolean = (IO.Path.GetExtension(path) = "")
'returns False

Надеюсь, это может быть кому-то полезно!

person lhan    schedule 18.10.2012
comment
пробовали ли вы использовать метод Path.HasExtension? ? - person Jake Berger; 03.11.2012
comment
Если его не существует, значит, это не файл или каталог. Любое имя может быть создано как любое. Если вы намереваетесь его создать, тогда вам следует знать, что вы создаете, а если нет, то зачем вам эта информация? - person Random832; 22.12.2013
comment
Папка может называться test.txt, а файл может называться test - в этих случаях ваш код будет возвращать неверные результаты. - person Stephan Bauer; 22.08.2014
comment
В классах System.IO.FIle и System.IO.Directory есть метод .Exists. вот что нужно сделать. Каталоги могут иметь расширения; Я часто это вижу. - person TomXP411; 26.02.2015

так поздно в игре я знаю, но думал, что все равно поделюсь этим. Если вы работаете исключительно с путями как со строками, выяснить это проще простого:

private bool IsFolder(string ThePath)
{
    string BS = Path.DirectorySeparatorChar.ToString();
    return Path.GetDirectoryName(ThePath) == ThePath.TrimEnd(BS.ToCharArray());
}

например: ThePath == "C:\SomeFolder\File1.txt" в конечном итоге будет таким:

return "C:\SomeFolder" == "C:\SomeFolder\File1.txt" (FALSE)

Другой пример: ThePath == "C:\SomeFolder\" в конечном итоге будет таким:

return "C:\SomeFolder" == "C:\SomeFolder" (TRUE)

И это также будет работать без обратной косой черты в конце: ThePath == "C:\SomeFolder" в конечном итоге будет таким:

return "C:\SomeFolder" == "C:\SomeFolder" (TRUE)

Имейте в виду, что это работает только с самими путями, а не с отношениями между путем и "физическим диском" ... поэтому он не может сказать вам, существует ли путь / файл или что-то в этом роде, но он уверен может сказать вам, путь к папке или к файлу ...

person MaxOvrdrv    schedule 17.09.2014
comment
Не работает с System.IO.FileSystemWatcher, поскольку при удалении каталога он отправляет c:\my_directory в качестве аргумента, который является таким же, когда удаляется файл без расширения c:\my_directory. - person Ray Cheng; 27.12.2014
comment
GetDirectoryName('C:\SomeFolder') возвращает 'C:\', поэтому ваш последний случай не работает. Это не делает различий между каталогами и файлами без расширений. - person Lucy; 07.07.2015
comment
Вы ошибочно предполагаете, что путь к каталогу всегда будет включать последний \. Например, Path.GetDirectoryName("C:\SomeFolder\SomeSubFolder") вернет C:\SomeFolder. Обратите внимание, что ваши собственные примеры того, что возвращает GetDirectoryName, показывают, что он возвращает путь, который не заканчивается обратной косой чертой. Это означает, что если кто-то использует GetDirectoryName в другом месте, чтобы получить путь к каталогу, а затем передает его вашему методу, он получит неправильный ответ. - person ToolmakerSteve; 02.04.2018

Если вы хотите найти каталоги, включая те, которые помечены как «скрытые» и «системные», попробуйте следующее (требуется .NET V4):

FileAttributes fa = File.GetAttributes(path);
if(fa.HasFlag(FileAttributes.Directory)) 
person jamie    schedule 26.02.2013

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

if (!Directory.Exists(@"C:\folderName")) return;
person Joe Stellato    schedule 16.03.2015

Понятно, я опоздал на вечеринку на 10 лет. Я столкнулся с ситуацией, когда из некоторого свойства я могу получить либо имя файла, либо полный путь к нему. Если путь не указан, я должен проверить существование файла, добавив «глобальный» путь к каталогу, предоставленный другим свойством.

В моем случае

var isFileName = System.IO.Path.GetFileName (str) == str;

сделали свое дело. Хорошо, это не волшебство, но, возможно, это поможет кому-то несколько минут разобраться. Поскольку это всего лишь синтаксический анализ строки, имена каталогов с точками могут давать ложные срабатывания ...

person dba    schedule 08.04.2019

    `public bool IsDirectory( string path ) {
        return string.IsNullOrEmpty( Path.GetFileName( path ) ) || Directory.Exists( path );
    }`

Проверяет, является ли имя файла пути пустой строкой или каталог существует. Таким образом, у вас не будет ошибки атрибутов файла, но при этом будет обеспечена избыточность на случай возможного сбоя.

person user15278186    schedule 21.05.2021

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

private static bool isDirectory(string path)
{
    bool result = true;
    System.IO.FileInfo fileTest = new System.IO.FileInfo(path);
    if (fileTest.Exists == true)
    {
        result = false;
    }
    else
    {
        if (fileTest.Extension != "")
        {
            result = false;
        }
    }
    return result;
}
person Stu1983    schedule 22.02.2012
comment
Расширение FileInfo - это (IMAO) хороший вариант для проверки несуществующих путей - person dataCore; 21.03.2013
comment
ваше второе состояние (иначе) неприятно. если это не существующий файл, то вы не знаете, что это могло быть (каталоги также могут заканчиваться чем-то вроде .txt). - person nawfal; 13.06.2013

Используя выбранный ответ в этом сообщении, я просмотрел комментарии и выразил доверие @ ŞafakGür, @Anthony и @Quinn Wilson за их информационные фрагменты, которые привели меня к этому улучшенному ответу, который я написал и протестировал:

    /// <summary>
    /// Returns true if the path is a dir, false if it's a file and null if it's neither or doesn't exist.
    /// </summary>
    /// <param name="path"></param>
    /// <returns></returns>
    public static bool? IsDirFile(this string path)
    {
        bool? result = null;

        if(Directory.Exists(path) || File.Exists(path))
        {
            // get the file attributes for file or directory
            var fileAttr = File.GetAttributes(path);

            if (fileAttr.HasFlag(FileAttributes.Directory))
                result = true;
            else
                result = false;
        }

        return result;
    }
person Mike Socha III    schedule 31.03.2015
comment
Кажется немного расточительным проверять атрибуты после того, как уже проверено наличие каталога / файла ()? Только эти два звонка делают всю необходимую здесь работу. - person Gone Coding; 26.08.2016

Возможно для UWP C #

public static async Task<IStorageItem> AsIStorageItemAsync(this string iStorageItemPath)
    {
        if (string.IsNullOrEmpty(iStorageItemPath)) return null;
        IStorageItem storageItem = null;
        try
        {
            storageItem = await StorageFolder.GetFolderFromPathAsync(iStorageItemPath);
            if (storageItem != null) return storageItem;
        } catch { }
        try
        {
            storageItem = await StorageFile.GetFileFromPathAsync(iStorageItemPath);
            if (storageItem != null) return storageItem;
        } catch { }
        return storageItem;
    }
person Minute V    schedule 14.06.2018

Очень поздно на вечеринке, но я обнаружил, что возвращаемое значение Nullable<Boolean> довольно уродливое - IsDirectory(string path) возвращение null не означает несуществующий путь без подробных комментариев, поэтому я придумал следующее:

public static class PathHelper
{
    /// <summary>
    /// Determines whether the given path refers to an existing file or directory on disk.
    /// </summary>
    /// <param name="path">The path to test.</param>
    /// <param name="isDirectory">When this method returns, contains true if the path was found to be an existing directory, false in all other scenarios.</param>
    /// <returns>true if the path exists; otherwise, false.</returns>
    /// <exception cref="ArgumentNullException">If <paramref name="path"/> is null.</exception>
    /// <exception cref="ArgumentException">If <paramref name="path"/> equals <see cref="string.Empty"/></exception>
    public static bool PathExists(string path, out bool isDirectory)
    {
        if (path == null) throw new ArgumentNullException(nameof(path));
        if (path == string.Empty) throw new ArgumentException("Value cannot be empty.", nameof(path));

        isDirectory = Directory.Exists(path);

        return isDirectory || File.Exists(path);
    }
}

Этот вспомогательный метод написан так, чтобы быть достаточно подробным и кратким, чтобы понять цель при первом чтении.

/// <summary>
/// Example usage of <see cref="PathExists(string, out bool)"/>
/// </summary>
public static void Usage()
{
    const string path = @"C:\dev";

    if (!PathHelper.PathExists(path, out var isDirectory))
        return;

    if (isDirectory)
    {
        // Do something with your directory
    }
    else
    {
        // Do something with your file
    }
}
person martinthebeardy    schedule 13.09.2019

Просто добавляю бахрому - Выбор папки. в пути

В моем приложении я получаю недавно открытые пути, переданные мне, некоторые из которых имеют выбор папки. в конце.

Некоторые FileOpenDialogs и WinMerge добавляют выбор папки. к тропам (это правда).

Диалоговое окно, показывающее выбор папки. Добавляется в путь

Но под Windows OS Folder Selection. не рекомендуется использовать имя файла или папки (например, никогда не делайте этого - качает кулаком). Как сказано здесь: http://msdn.microsoft.com/en-us/library/aa365247%28VS.85%29.aspx

Не заканчивайте имя файла или каталога пробелом или точкой. Хотя базовая файловая система может поддерживать такие имена, оболочка Windows и пользовательский интерфейс - нет. Однако допустимо указывать точку в качестве первого символа имени. Например, .temp.

Итак, пока выбрана папка. не следует использовать, можно. (классно).

Достаточно объяснений - мой код (мне очень нравятся перечисления):

public static class Utility
{
    public enum ePathType
    {
        ePathType_Unknown = 0,
        ePathType_ExistingFile = 1,
        ePathType_ExistingFolder = 2,
        ePathType_ExistingFolder_FolderSelectionAdded = 3,
    }

    public static ePathType GetPathType(string path)
    {
        if (File.Exists(path) == true) { return ePathType.ePathType_ExistingFile; }
        if (Directory.Exists(path) == true) { return ePathType.ePathType_ExistingFolder; }

        if (path.EndsWith("Folder Selection.") == true)
        {
            // Test the path again without "Folder Selection."
            path = path.Replace("\\Folder Selection.", "");
            if (Directory.Exists(path) == true)
            {
                // Could return ePathType_ExistingFolder, but prefer to let the caller known their path has text to remove...
                return ePathType.ePathType_ExistingFolder_FolderSelectionAdded;
            }
        }

        return ePathType.ePathType_Unknown;
    }
}
person TinyRacoon    schedule 12.08.2020

Разве это не сработает?

var isFile = Regex.IsMatch(path, @"\w{1,}\.\w{1,}$");
person Community    schedule 20.11.2015
comment
Это не сработает только потому, что в именах папок могут быть точки. - person KSib; 01.08.2016
comment
Также в файлах не обязательно должна быть точка. - person Keith Pinson; 03.03.2017