检查Path是文件还是目录的更好方法是什么?

SnA*_*BaZ 359 .net c# directory file path

我正在处理一个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;
}
Run Code Online (Sandbox Code Playgroud)

我不禁觉得有更好的方法来做到这一点!我希望找到一个标准的.NET方法来处理这个问题,但我无法做到这一点.是否存在这样的方法,如果不存在,确定路径是文件还是目录的最直接的方法是什么?

Qui*_*son 552

如何判断路径是文件还是目录:

// 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");
Run Code Online (Sandbox Code Playgroud)

.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");
Run Code Online (Sandbox Code Playgroud)

  • 不适用于不存在的文件/文件夹的路径 (66认同)
  • @Key:在.NET 4.0之后,可以使用`attr.HasFlag(FileAttributes.Directory)`. (26认同)
  • @ŞafakGür:不要在时间敏感的循环中这样做.attr.HasFlag()很慢,并且每次调用都使用Reflection (12认同)
  • +1这是更好的方法,并且明显快于我提出的解决方案. (7认同)
  • @ KeyMs92它的按位数学.基本上,attr是一些二进制值,一位意味着"这是一个目录".按位和"&"运算符将返回一个二进制值,其中只有两个操作数中的(1)位都打开.在这种情况下,如果打开目录文件属性位,对`attr`和`FileAttributes.Directory`值执行按位和操作将返回`FileAttributes.Directory`的值.有关更好的解释,请参见http://en.wikipedia.org/wiki/Bitwise_operation. (6认同)
  • @jberger如果路径不存在,那么`C:\ Temp`是否指向名为`Temp`的目录或名为`Temp`的文件是不明确的.代码意味着什么? (6认同)
  • 试试这个!(在粘贴到编辑器中并重新格式化之后;))`//如果路径是dir则返回true,如果是文件则返回false,如果它既不存在也不存在则返回null.公共静态布尔?IsDirFile(这个字符串路径){bool?result = null; if(Directory.Exists(path)|| File.Exists(path)){//获取文件或目录的文件属性var fileAttr = File.GetAttributes(path); if(fileAttr.HasFlag(FileAttributes.Directory))result = true; else result = false; 返回结果; }` (5认同)
  • @ springy76:它比按位比较慢[[16次,根据Will](http://stackoverflow.com/q/7368652/704144))但除非它处于一个非常时间关键的循环中,我会说使用HasFlag尽管它与直接按位比较相对缓慢,但它更具表现力并因此更受欢迎.与往常一样,OP应该做一些测试来决定是否避免HasFlag在他的特定场景中是微优化. (3认同)
  • 在我看来,这是"正式"的方式.路要走! (2认同)
  • 我喜欢迈克的选择。上面的解决方案创建了一个例外。+1 (2认同)
  • 迈克的版本略有简化:public static bool?IsDirFile(字符串路径){if(!Directory.Exists(path)&&!File.Exists(path))返回null; var fileAttr = File.GetAttributes(path); return!fileAttr.HasFlag(FileAttributes.Directory); } (2认同)
  • 任何人都可以解释为什么这是一个非常积极的正确答案和Directory.Exists不是?Directory.Exists基本上做了同样的事情,只有我可以解决,只有更健壮的方式.我认为这是一篇文章,其中SO答案实际上有点误导. (2认同)

lla*_*oo7 233

用这些怎么样?

File.Exists();
Directory.Exists();
Run Code Online (Sandbox Code Playgroud)

  • 与`File.GetAttributes()`不同,这也具有不在无效路径上抛出异常的优点. (37认同)
  • 如果您担心不存在的文件/文件夹,试试这个`public static bool?IsDirectory(字符串路径){``if(Directory.Exists(path))``return true; //是一个目录``else if(File.Exists(path))``return false; //是一个文件``else``返回null; //什么都不是``}` (8认同)
  • @jberger我希望它不适用于不存在的文件/文件夹的路径.File.Exists("c:\\ temp \\nonexistant.txt")应该返回false,就像它一样. (3认同)

小智 20

只有这一行,如果路径是目录或文件,您可以获得:

File.GetAttributes(data.Path).HasFlag(FileAttributes.Directory)
Run Code Online (Sandbox Code Playgroud)

  • 请注意,至少需要.NET 4.0.如果path不是有效路径,这也会爆炸. (4认同)
  • 如果您已经创建了 FileInfo 对象并正在使用实例的 Exists 属性,为什么不访问其 Attributes 属性而不是使用静态 File.GetAttributes() 方法呢? (2认同)

Ron*_*rby 9

这是我的:

    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));
    }
Run Code Online (Sandbox Code Playgroud)

它与其他人的答案类似但不完全相同.

  • “如果有扩展名,那么它是一个文件” - 这不是真的。文件不必有扩展名(即使在 Windows 中也是如此),而目录可以有“扩展名”。例如,这可以是文件或目录:“C:\Newfolder.log” (4认同)
  • 从技术上讲,你应该使用`Path.DirectorySeparatorChar`和`Path.AltDirectorySeparatorChar` (3认同)
  • 这个猜测意图的想法很有趣。恕我直言,最好分为两种方法。方法一进行存在性测试,返回一个可为空的布尔值。如果调用者随后想要“猜测”部分,则针对一的空结果,然后调用方法二来进行猜测。 (2认同)
  • 我会将此重写为返回一个元组,无论它是否猜测。 (2认同)
  • @bytedev我知道,但是在函数的这一点上,代码正在猜测意图。甚至有评论说。大多数文件都有扩展名。大多数目录没有。 (2认同)

Mic*_*key 6

作为Directory.Exists()的替代方法,您可以使用File.GetAttributes()方法来获取文件或目录的属性,因此您可以创建一个这样的帮助方法:

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

在填充包含该项的其他元数据的控件时,您还可以考虑将对象添加到TreeView控件的tag属性.例如,您可以为文件添加FileInfo对象,为目录添加DirectoryInfo对象,然后在tag属性中测试项类型,以便在单击项时进行额外的系统调用以获取该数据.

  • 而不是那个可怕的逻辑块,尝试`isDirectory =(fa&FileAttributes.Directory)!= 0);` (6认同)
  • 这与其他的有什么不同[答案](http://stackoverflow.com/a/1395226/503501) (2认同)

HAL*_*000 5

鉴于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;
    }
}
Run Code Online (Sandbox Code Playgroud)

以下是测试方法:

    [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());
    }
Run Code Online (Sandbox Code Playgroud)


drz*_*aus 5

结合其他答案的建议后,我意识到我想到了与Ronnie Overby的答案相同的东西。以下是一些测试,指出了一些需要考虑的事项:

  1. 文件夹可以具有“扩展名”: C:\Temp\folder_with.dot
  2. 文件不能以目录分隔符(斜杠)结尾
  3. 从技术上讲,有两个目录分隔符是特定于平台的-即可以或可以不是斜杠(Path.DirectorySeparatorCharPath.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);
}
Run Code Online (Sandbox Code Playgroud)

结果

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 
Run Code Online (Sandbox Code Playgroud)

方法

/// <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)
{
    // /sf/ask/97664381/
    // turns out to be about the same as /sf/answers/1371777501/

    // 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;
}
Run Code Online (Sandbox Code Playgroud)