最稳妥方式是直接调用file.exists和Directory.exists。二者不依赖路径末尾斜杠,不受符号链接或权限干扰(仅需基本读取权限),但返回false可能因路径不存在、权限不足或格式非法,故建议先用path.ispathrooted等校验路径合法性。

用 File.Exists 和 Directory.Exists 分别判断最稳妥
直接调用这两个方法是最常用、最安全的方式。它们不依赖路径字符串的末尾是否带反斜杠,也不受符号链接或权限限制的干扰(只要当前进程有基本读取权限)。
注意:二者返回 false 并不意味着路径一定不存在——也可能是权限不足或路径格式非法(如含控制字符)。所以实际使用时建议先用 Path.IsPathRooted 或 Path.GetInvalidPathChars() 做基础校验。
-
File.Exists(@"C: est.txt")→true表示是文件 -
Directory.Exists(@"C: est")→true表示是文件夹 - 如果两者都为
false,大概率是路径不存在;若一个为true,另一个必为false(同一路径不能同时是文件和目录)
避免误判:别只看路径末尾有没有反斜杠
很多人以为加了 就是目录、不加就是文件,这是错的。windows 下 notepad.exe 和 notepad.exe 都能被系统识别为同一文件(后者只是被自动忽略末尾斜杠),Directory.Exists("notepad.exe") 会返回 false,但 File.Exists("notepad.exe") 仍为 true。
更危险的是,某些网络路径或重解析点(如 NTFS 符号链接)可能让末尾斜杠误导判断。靠字符串特征做判断在生产环境极易出错。
- ❌ 错误做法:
path.EndsWith("") || path.EndsWith("/")) - ✅ 正确做法:始终走
File.Exists/Directory.Exists实际探测 - 特殊场景如需快速预判(比如大量路径批量处理),可先用
Path.GetFileName(path) == ""粗筛,但必须再用 Exists 方法二次确认
当路径存在但权限不足时,Exists 方法会静默返回 false
这是最容易被忽略的一点。如果目标路径所在卷已断开、ACL 拒绝遍历、或位于受限的系统目录(如 C:WindowsSystem32),File.Exists 和 Directory.Exists 都不会抛异常,而是直接返回 false —— 和“路径不存在”表现完全一致。
若业务逻辑必须区分“不存在”和“无权限”,就得捕获 UnauthorizedAccessException 或 IOException,改用 FileInfo / DirectoryInfo 构造函数并检查 Exists 属性:
try { var fi = new FileInfo(path); if (fi.Exists) { /* 是文件 */ } else if (fi.Directory.Exists) { /* 路径父目录存在,但文件本身不存在 */ } } catch (UnauthorizedAccessException) { /* 明确知道是权限问题 */ }
用 FileSystemInfo 统一获取类型信息
如果需要一次性拿到路径的类型、创建时间、属性等元数据,推荐用 FileSystemInfo 的工厂方法 FileSystemInfo.GetFileSystemInfo:
它会自动返回 FileInfo 或 DirectoryInfo 实例,再通过 GetType() 或 is 判断即可:
var info = FileSystemInfo.GetFileSystemInfo(path);-
if (info is FileInfo)→ 文件 -
if (info is DirectoryInfo)→ 文件夹 - 这个方法内部仍调用
Exists,所以同样受权限影响;但它避免了重复构造对象,适合后续还需读取属性的场景
真正复杂的地方不在怎么写判断逻辑,而在于你是否考虑过:路径存在但不可访问、路径指向重解析点、或者跨文件系统挂载时的语义差异。这些边界情况往往在测试环境里不暴露,上线后才突然冒出来。