.NET如何检查path是否是文件而不是目录?


76

我有一个路径,我需要确定它是目录还是文件。

这是确定路径是否为文件的最佳方法吗?

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);

如果两者都不存在,那我就不会去做任何一个分支。因此,假设它们确实存在。



Answers:


117

使用:

System.IO.File.GetAttributes(string path)

并检查返回的FileAttributes结果是否包含值FileAttributes.Directory

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

15
只需确保您尝试/执行此操作,因为该路径甚至可能不存在。
LBushkin 2010年

如果路径中包含通配符,会发生什么?我得到一个非法的字符参数,但是如果我使用通配符,那对我的用户来说是一条合法的路径怎么办?
Michael Sheely '16

1
@MichaelSheely-AFAIK,要处理通配符,您必须Directory.GetFiles使用字符串调用,并查看结果是否计数大于零。“通配符路径”不是路径。这是一种模式
ToolmakerSteve

55

我认为这是只需要两次检查的最简单方法:

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
}

我没有投票给你,但是它的答案肯定是“简单的”,只需要打一个电话(而不是两个)。
Christian.K,

9
这种方法的优点是,即使文件系统中根本没有匹配的条目,它也可以工作(换句话说,它既不是文件夹也不是文件)。从这个意义上讲,它是“简单的”。顺便提及,OP说的是“路径”,而不是“已知存在的路径”。

6
是的,实际上,当您不确定要调查的路径是否存在时,我认为这是更好的答案。不必担心捕获异常,这很重要。
Ben Collins

1
我同意这种方法是有效的。我只是创建了一个微型实用程序来识别指定的名称是文件还是目录,并且此方法使返回1目录,2文件和0错误(例如,名称无效)变得极其简单。该工具很小(338字节源,3584字节已编译),运行速度非常快。
Synetech

1
@TomPadilla:如果该路径不存在,您究竟希望发生什么?
Dirk Vollmar 2014年

11

您可以使用一些互操作代码执行此操作:

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

为了进一步澄清一些评论...

在.NET中引入非托管代码并不比.NET中的任何其他文件或与I / O相关的调用具有更大的固有危险,因为它们最终都会调用非托管代码。

这是使用字符串的单个函数调用。您不会通过调用此函数来引入任何新的数据类型和/或内存使用情况。是的,您确实需要依靠非托管代码来正确清理,但是最终您将依赖于大多数与I / O相关的调用。

供参考,这是Reflector的File.GetAttributes(string path)的代码:

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提出安全要求的唯一原因是因为它需要读取文件的属性,因此它想确保调用代码具有这样做的权限。这与基础操作系统检查(如果有)不同。您始终可以围绕对PathIsDirectory的P / Invoke调用创建包装函数,如果需要的话,还需要某些CAS权限。


3
这似乎是一项工作,以确定路径是文件还是目录。
David Basarab

2
我不明白为什么这会被否决,尽管仅使用.NET功能保留在托管代码中会容易得多。
Dirk Vollmar 09年

1
如果路径是文件或目录,则引入非托管代码很危险。我必须依靠调用函数来正确清理内存,否则我的代码可能会泄漏。
David Basarab

1
我仍然看不到为什么这会被否决,因为它使用不提供歧义程度的方法正确地回答了这个问题。
Scott Dorman

4
那就是SO的“美丽”,即使是一个很好的答案也可能会被一些狂热者所
否决


4

看一下这个:

/// <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);
}

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



1

鉴于特定的路径字符串不能同时表示目录文件,因此以下内容可以正常工作,并为其他操作打开了大门。

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

如果您正在使用文件系统,则使用FileInfoDirectoryInfo比使用字符串要简单得多。


查看0xA3的答案,调用imo会更好一些。
nawfal

或者只是(Directory.Exists(src))...如果是文件,它将为false。如果src是目录,它将为false。如果src是不存在的目录,那么根据定义src不能是目录。
克里斯·博德曼

-3

嗯,看起来Files该类(中的java.nio)实际上具有静态isDirectory方法。因此,我认为您实际上可以使用以下内容:

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

4
寻找.NET解决方案。
David Basarab 2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.