谨慎使用 FileInfo.Exists 实例方法,而是使用 File.Exists 静态方法替代
如果你在代码中使用了 FileInfo.Exists 实例方法来判断一个文件是否存在,也许会发现此方法可能错误地判断来一个文件是否真的存在。这是一个坑。
本文将介绍坑的原因,并提供填坑的办法。
问题代码
我们使用两种不同的方式判断文件是否存在:
FileInfo.Exists实例方法File.Exists静态方法
static async Task Main(string[] args)
{
var filePath = @"C:\Users\lvyi\Desktop\walterlv.log";
var fileInfo = new FileInfo(filePath);
while (true)
{
Console.WriteLine($"FileInfo.Exists = {fileInfo.Exists}");
Console.WriteLine($" File.Exists = {File.Exists(filePath)}");
Console.WriteLine("----");
await Task.Delay(1000);
}
}
现在运行这个程序,我们会发现,中途删除了 walterlv.log 文件之后,FileInfo.Exists 依然返回了 true,而 File.Exists 已经开始返回 false 了。

原因分析
实际翻阅代码可以发现,FileInfo.Exists 和 File.Exists 方法最终都是使用相同的方法来完成文件存在与否的判断。
这是 FileInfo.Exists 的判断:
public override bool Exists
{
[SecuritySafeCritical] get
{
try
{
if (this._dataInitialised == -1)
this.Refresh();
if (this._dataInitialised != 0)
return false;
return (this._data.fileAttributes & 16) == 0;
}
catch
{
return false;
}
}
}
这是 File.Exists 的最终判断:
public static bool FileExists(string fullPath)
{
Interop.Kernel32.WIN32_FILE_ATTRIBUTE_DATA data = new Interop.Kernel32.WIN32_FILE_ATTRIBUTE_DATA();
int errorCode = FillAttributeInfo(fullPath, ref data, returnErrorOnNotFound: true);
return (errorCode == 0) && (data.dwFileAttributes != -1)
&& ((data.dwFileAttributes & Interop.Kernel32.FileAttributes.FILE_ATTRIBUTE_DIRECTORY) == 0);
}
只不过,FileInfo.Exists 只会在没有初始化的时候初始化一次,而 File.Exists 是没有缓存的,每次都是直接去获取文件的属性(这就涉及到 IO)。
解决办法
所以,如果你正在处理的文件在不同的时间可能存在也可能不存在,那么最好使用 File.Exists 来判断文件存在与否,而不是使用 FileInfo.Exists 来判断。
不过,如果你需要一次性判断文件的非常多的信息(而不只是文件存在与否),那么依然建议使用 FileInfo,只不过在使用之前需要调用 Refresh 进行一次刷新。
我的博客会首发于 https://walterlv.com/,而 CSDN 和博客园仅从其中摘选发布,而且一旦发布了就不再更新。

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名吕毅(包含链接:https://blog.csdn.net/wpwalter),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系。
谨慎使用 FileInfo.Exists 实例方法,而是使用 File.Exists 静态方法替代的更多相关文章
- Linux启动网卡时出现RTNETLINK answers: File exists错误解决方法
这里说一下,如果复制了虚拟机,设置新的MAC地址为什么? 在虚拟机的网络设置中--->高级.然后找到如下窗口,生成新的MAC地址即可. ----------------------------- ...
- RTNETLINK answers: File exists错误解决方法
>一.写在前面: 因为是我刚学习linux好多问题需要解决,bolg仅作为记录自己的在技术这条道路上的点点滴滴. 二.事件起因: 最近因为女友的原因消沉的好长时间,在马哥那里的课程的结束到现在已 ...
- Git – fatal: Unable to create ‘/.git/index.lock’: File exists错误解决办法
有时候在提交的时候,中间提交出错,导致有文件被lock,所以会报下面的错误: fatal: Unable to create ‘/msg/.git/index.lock’: File exists. ...
- linux下RTNETLINK answers: File exists的解决方案
重启网卡时 出现 :RTNETLINK answers: File exists 提示 以下是网卡出来错误的解决方法: 第一种: 和 NetworkManager 服务有冲突,这个好解决,直接关闭 ...
- IIS目录下文件共享后System.IO.File.Exists返回false
场景:在iis目录下,因为特殊需要共享一个文件夹,给到其他的技术人员访问,突然发现小小的操作,搞“大”了,使用 string path = Server.MapPath("~/file/te ...
- RTNETLINK answers: File exists错误
解决ssh连接虚拟机出错,RTNETLINK answers: File exists 解决步骤如下: 使用ssh连接虚拟机的时候,发现目标主机无法连接,登录虚拟机,查看ssh监听是否开启: 发现监听 ...
- docker dead but pid file exists
CentOS 6安装docker 报docker dead but pid file exists 执行 yum install epel-release yum install docker-io ...
- npm ERR! File exists: /XXX/xxx npm ERR! Move it away, and try again.
今天抽空将我的静态服务 ks-server 之前留下的 bug(在node低版本情况下报错)维护了一下. 当我重新 npm link 时,如下错误: npm WARN ks-server@1.0.2 ...
- Centos7修改默认网卡名(改为eth0)以及网卡启动报错RTNETLINK answers: File exists处理
安装好centos7版本的系统后,发现默认的网卡名字有点怪,为了便于管理,可以手动修改.下面对centos7版本下网卡重命名操作做一记录:1)编辑网卡信息[root@linux-node2~]# cd ...
随机推荐
- Spring AMQP 源码分析 02 - CachingConnectionFactory
### 准备 ## 目标 了解 CachingConnectionFactory 在默认缓存模式下的工作原理 ## 前置知识 <Spring AMQP 源码分析 01 - Impatie ...
- Java 访问权限修饰符以及protected修饰符的理解
2017-11-04 22:28:39 访问权限修饰符的权限 访问修饰符protected的权限理解 在Core Java中有这样一段话“在Object类中,clone方法被声明为protected, ...
- eclipse wtp 没有自动生成 web.xml
因此,运行servlet 时出错了. 网上查了一下,好像说确实不会自动生成,但是运行应该没有问题的. 幸亏找到了手动生成web.xml的方法,也就不纠结了. http://crunchify.com/ ...
- Redis分布式锁实现简单秒杀功能
这版秒杀只是解决瞬间访问过高服务器压力过大,请求速度变慢,大大消耗服务器性能的问题. 主要就是在高并发秒杀的场景下,很多人访问时并没有拿到锁,所以直接跳过了.这样就处理了多线程并发问题的同时也保证了服 ...
- 013 - 关于GC root: Native Stack | MAT分析
Question: I have some third library code that I run and after some time I run into OutOfMemoryEr ...
- golang martini 源码阅读笔记之inject
martini是go语言写的一个超级轻量的web开源框架,具体源码可在github搜索找到.13年那会开始接触go语言时有稍微看过这个框架,由于之后没有继续使用go就慢慢忽略了,最近由于手头项目可能会 ...
- 我的Java学习笔记 -开发环境搭建
开始学习Java~ 一.Java简介 Java编程语言是一种简单.面向对象.分布式.解释型.健壮安全.与系统无关.可移植.高性能.多线程和动态的语言. Java分为三个体系: JavaSE(J2SE) ...
- 『科学计算』科学绘图库matplotlib练习
思想:万物皆对象 作业 第一题: import numpy as np import matplotlib.pyplot as plt x = [1, 2, 3, 1] y = [1, 3, 0, 1 ...
- OC MRC之 @property参数(代码分析)
第一部分 // // main.m // 04-@property参数 // // Created by apple on 13-8-9. // Copyright (c) 2013年 itcast. ...
- DB2性能调优
1.更新统计信息 --更新数据库所有表统计信息 --连接到数据库(-v选项,表示要回显命令,以下同) db2 -v connect to DB_NAME --查看是否收集过统计信息,什么时候更新的 ...