File.Exists 是最直接、最安全的判断文件是否存在的方式,但不解决并发竞态问题,也不能替代权限检查;它底层调用系统API、开销小,仅确认路径存在且为文件,不保证可读,非法字符会抛 ArgumentException,网络路径可能因超时误报 false。

File.Exists 是最直接、最安全的判断方式,但要注意它不解决并发场景下的竞态问题,也不能替代权限检查。
用 File.Exists 判断文件是否存在(基础且常用)
这是 .NET 提供的标准 API,底层调用操作系统 API,开销极小,适合绝大多数静态检查场景。
- 返回
true仅表示路径存在且是文件(不是目录),不保证你有读取权限 - 路径中包含非法字符(如
、<code>|)会直接抛出ArgumentException,建议先用Path.GetInvalidPathChars()过滤或 try-catch - 网络路径(如
\servershareile.txt)可能因超时返回false,不是文件真不存在,而是访问被阻塞或拒绝 - 示例:
bool exists = File.Exists(@"C: empconfig.json");
为什么不用 FileInfo.Exists?
FileInfo 构造函数本身不检查文件是否存在,只有访问 Exists 属性时才触发一次系统调用——和 File.Exists 效果一致,但多了一次对象分配开销。
- 如果你已经持有
FileInfo实例(比如遍历目录后拿到的),用它的Exists属性没问题 - 如果只是单纯判断存在性,直接用
File.Exists更轻量,避免无谓的 GC 压力 - 注意:
new FileInfo("nonexistent.txt").Exists不会抛异常,只是返回false
并发写入时,File.Exists + File.Create 会出问题
这是最容易被忽略的坑:两个线程同时执行“判断不存在 → 创建文件”,可能导致一个线程覆盖另一个的写入,或抛出 IOException(文件已存在)。
- 正确做法是直接尝试创建,并捕获
IOException或使用FileMode.CreateNew: try { using (var fs = new FileStream(path, FileMode.CreateNew)) { } } catch (IOException ex) when (ex.Message.Contains("already exists")) { /* 文件已存在 */ }- 或者用
File.Open(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None)配合锁逻辑,但需自行处理初始内容写入
判断前要不要先检查路径合法性?
对用户输入或外部传入的路径,必须做基础校验,否则 File.Exists 可能抛出未预期异常,中断流程。
- 用
Path.IsPathRooted判断是否为绝对路径(相对路径依赖当前工作目录,行为不稳定) - 用
Path.GetFullPath展开相对路径并规范化,再检查长度是否超限(Windows 最大路径 260 字符,可用\?前缀绕过,但需手动拼接) - 避免在判断前就调用
Directory.GetParent或File.GetAttributes,它们可能抛出UnauthorizedAccessException,而File.Exists不会(只要路径格式合法)
真正麻烦的从来不是“怎么判断”,而是“判断之后该信什么”——文件存在不代表可读,不存在也不代表不能创建,尤其在 UNC 路径、容器挂载卷、OneDrive 同步目录等场景下,Exists 返回值只是瞬时快照。


















