更好的方式检查路径是文件还是目录?

490

我正在处理一个目录和文件的 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 方法来处理这个问题,但我没有找到。是否存在这样的方法?如果不存在,最直接的方法是确定一个路径是文件还是目录?


11
可以有人编辑问题标题,以明确指定“现有”的文件/目录吗?所有答案都适用于磁盘上存在的文件/目录的路径。 - Jake Berger
1
@jberger请参考我下面的答案。我找到了一种方法来处理可能存在或不存在的文件/文件夹路径。 - lhan
你是如何填充这个树形视图的?你是如何获取其中的路径的? - Random832
23个回答

2

如果你只是在使用字符串路径进行编程,那么解决这个问题非常简单:

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

请注意,这仅适用于路径本身,而不是路径与物理磁盘之间的关系,因此它无法告诉您路径/文件是否存在等信息,但它确实可以告诉您路径是文件夹还是文件。

2
由于当目录被删除时,System.IO.FileSystemWatcher 发送 c:\my_directory 作为参数,而删除无扩展名文件 c:\my_directory 时也是如此,因此它与 System.IO.FileSystemWatcher 不兼容。 - Ray Cheng
GetDirectoryName('C:\SomeFolder') 返回 'C:\',所以你的最后一个情况不起作用。这不能区分没有扩展名的目录和文件。 - Lucy
你错误地假设目录路径总是包含最后的“\”。例如,Path.GetDirectoryName("C:\SomeFolder\SomeSubFolder")将返回C:\SomeFolder。请注意,你自己提供的GetDirectoryName返回的示例显示它返回不以反斜杠结尾的路径。这意味着如果有人在其他地方使用GetDirectoryName获取目录路径,然后将其提供给你的方法,他们将得到错误的答案。 - ToolmakerSteve

2

当我遇到类似问题时,我发现了以下解决方法。需要检查路径是否为文件或文件夹,即使该文件或文件夹实际上不存在。之前的答案中有一些评论提到它们不能适用于这种情况。我找到了一个解决方案(我使用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

希望这对某些人有所帮助!

1
你尝试过使用 Path.HasExtension 方法吗? - Jake Berger
如果它不存在,那么它既不是文件也不是目录。任何名称都可以被创建为其中之一。如果您打算创建它,那么您应该“知道”您正在创建什么,如果您不知道,那么您为什么需要这些信息呢? - Random832
9
一个文件夹可以命名为 test.txt,一个文件也可以命名为 test - 在这些情况下,你的代码会返回不正确的结果。 - Stephan Bauer
2
System.IO.File和System.IO.Directory类中有一个.Exists方法,这就是要做的事情。目录可以有扩展名;我经常看到它。 - TomXP411

1
我明白了,您晚了10年才来到这个聚会。我碰到的情况是,从某个属性中我可以得到文件名或完整的文件路径。如果没有提供路径,我必须通过附加另一个属性提供的“全局”目录路径来检查文件是否存在。
在我的情况下
var isFileName = System.IO.Path.GetFileName (str) == str;

解决了问题。 好的,这不是魔法,但或许可以帮助某人节省几分钟的理解时间。 由于这只是一个字符串解析,所以带有点的目录名称可能会产生误报...


1
我需要这个,这些帖子很有帮助,这将其简化成一行,如果路径根本不是一个路径,它只会返回并退出该方法。它解决了以上所有问题,也不需要尾随斜杠。
if (!Directory.Exists(@"C:\folderName")) return;

1

如果你想查找目录,包括那些被标记为“隐藏”和“系统”的目录,请尝试这个方法(需要 .NET V4):

FileAttributes fa = File.GetAttributes(path);
if(fa.HasFlag(FileAttributes.Directory)) 

0

使用此帖子上的选定答案,我查看了评论并认可@Ş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;
    }

在已经检查了目录/文件是否存在之后再检查属性似乎有些浪费?这两个调用已经完成了此处所需的所有工作。 - iCollect.it Ltd

0

可能是针对 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;
    }

0

这是我的解决方案,请注意我正在寻找一个严格避免任何不必要的文件系统访问的函数,但这里仅允许字符串操作(路径可能不存在):

public static bool IsFolder(string path)
{
    if (string.IsNullOrEmpty(path)) return false;
    if (path.EndsWith("\\")) return true;
    return (path.Contains("\\") && string.IsNullOrEmpty(Path.GetExtension(path)));
}

0
我使用以下代码,它还测试了扩展名,这意味着它可以用于测试所提供的路径是否是一个文件,但是一个不存在的文件。
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;
}

1
FileInfo扩展名是(IMAO)检查不存在路径的好选择。 - dataCore
2
你的第二个条件(否则)十分可疑。如果它不是一个已存在的文件,那么你不知道它可能是什么(目录也可以以像“.txt”这样的东西结尾)。 - nawfal

0
using System;
using System.IO;
namespace FileOrDirectory
{
     class Program
     {
          public static string FileOrDirectory(string path)
          {
               if (File.Exists(path))
                    return "File";
               if (Directory.Exists(path))
                    return "Directory";
               return "Path Not Exists";
          }
          static void Main()
          {
               Console.WriteLine("Enter The Path:");
               string path = Console.ReadLine();
               Console.WriteLine(FileOrDirectory(path));
          }
     }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接