.NET如何检查路径是否为文件而非目录?

81

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

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

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);
如果两个都不存在,那我就不会执行任何分支。所以假设它们都存在。

https://dev59.com/wHM_5IYBdhLWcg3wZSPX#17198139 - HAL9000
可能是重复的问题:更好的方法来检查路径是文件还是目录? - DavidRR
8个回答

124

使用:

System.IO.File.GetAttributes(string path)

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

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

16
请确保在 try/catch 块中执行此操作,因为该路径可能不存在。 - LBushkin
如果路径中有通配符会发生什么?我会得到一个非法字符参数的错误,但是如果我使用通配符并且这是我的用户的合法路径呢? - Michael Sheely
1
据我所知,要处理通配符,您必须使用字符串调用Directory.GetFiles,并查看结果是否大于零。 "带通配符的路径"不是路径。它是一个模式 - ToolmakerSteve
如果路径(文件夹或文件的目录)不存在,则无法工作。 - IulianT
@LeresAldtai 假设路径已经存在 - OP 没有要求检查路径不存在。 - Alnitak

58

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

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
}

9
这种方法的优点是,即使文件系统中没有匹配项(也就是说,它既不是文件夹也不是文件),它仍然可以正常工作;从这个意义上讲,它更加“简单”。顺便说一下,原帖中说的是“路径”,而不是“已知存在的路径”。 - Tao
6
当你不确定你正在调查的路径是否存在时,我认为这是更好的答案。不必担心捕获异常是很重要的事情。 - Ben Collins
1
我认为这种方法非常有效。我刚刚创建了一个小工具,用于识别指定名称是文件还是目录,而这种方法使得返回1表示目录,2表示文件,以及0表示错误(例如,名称无效)变得非常简单。该工具很小(源代码338字节,编译后3584字节),运行非常快。 - Synetech
不要依赖于这个答案,它是误导性的。这将告诉您文件或目录是否存在,而不是它们是什么类型的IO条目。如果路径不正确,两个检查都将返回false。 - Tom Padilla
2
@TomPadilla:如果路径不存在,您期望发生什么? - Dirk Vollmar
显示剩余5条评论

11

你可以使用一些Interop代码来实现这个:

    [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
    [return: MarshalAsAttribute(UnmanagedType.Bool)]
    public static extern bool PathIsDirectory([MarshalAsAttribute(UnmanagedType.LPWStr), In] string pszPath);
为了进一步澄清一些评论...
在.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进行安全性需求的唯一原因是因为它需要读取文件的属性,因此它希望确保调用代码有权限这样做。这与底层操作系统的检查(如果有)不同。如果需要,您始终可以在P / Invoke调用PathIsDirectory周围创建包装器函数,也会要求特定的CAS权限。


3
判断路径是文件还是目录好像需要做很多工作。 - David Basarab
2
我不明白为什么这个被踩了,虽然只使用.NET功能保持在托管代码中会更简单。 - Dirk Vollmar
1
我仍然不明白为什么这个回答会被踩,因为它用一种没有任何歧义的方法正确地回答了问题。 - Scott Dorman
4
这就是 Stack Overflow 的“美妙”之处,即使一个好的答案也可能会被一些狂热者踩下去 ;) - Wodzu
1
我所能看到的这个解决方案唯一可能存在的问题,就是操作系统未来版本中API的更改。.NET框架应该因为没有这个功能而被贬低。否则,这似乎是一个不错的解决方案。我非常注重性能,这比其他所有解决方案都要好得多!所以你得到了+1。 - JDC
显示剩余9条评论

7
假设目录已经存在...
bool isDir = (File.GetAttributes(path) & FileAttributes.Directory)
                  == FileAttributes.Directory;

如果路径不存在,GetAttributes将返回-1。 - Binary Worrier
1
文档似乎表明,如果文件不存在,它将抛出一个异常。http://msdn.microsoft.com/en-us/library/system.io.file.getattributes.aspx - tvanfosson

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

这篇文章介绍了如何在C#中检查文件夹是否存在的方法。以下是示例代码:

using System.IO;

public static bool IsFolder(string folderPath)
{
    return Directory.Exists(folderPath);
}

2

读取文件属性:

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

检查目录标志。


1

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

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

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

看看0xA3的回答,我认为调用稍微好一些。 - nawfal
或者只需 if (Directory.Exists(src)) ...如果是文件,它将为false。如果src是一个目录,它也会是false。如果src是一个不存在的目录,则根据定义,src不能是一个目录。 - Chris Bordeman

-4
嗯,看起来 java.nio 中的 Files 类实际上有一个静态的 isDirectory 方法。因此,我认为你可以使用以下代码:
Path what = ...
boolean isDir = Files.isDirectory(what);

4
寻找一个.NET解决方案。 - David Basarab

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