File.Exists("")和FileInfo exists有什么区别?

15

我在\ProgramFiles(x86)\MyAppFolder中有一个*.exe文件。

在x86应用程序中,我检查文件是否存在(64位系统)。 简单:

bool fileExists = File.Exists(@"\ProgramFiles(x86)\MyAppFolder\Manager.exe");

结果是:“fileExists == false”(实际上文件是存在的)。据我了解,这是虚拟化引起的问题。这个问题在这里有描述:here。没问题。

但下一段代码:
bool fileExists = new FileInfo("\\Path").Exists;

"fileExists == true"

为什么第一种情况和第二种情况的结果不同?

var controller = new ServiceController(Product.ServiceName);
_manager.Enabled = controller.Status == ServiceControllerStatus.Running;

var info = new DirectoryInfo(Assembly.GetExecutingAssembly().Location);

var s = File.Exists(@"D:\TFS\GL_SOURCES\Teklynx_LPM\Dev\Server\Debug\Manager.exe");

string pathToManager = string.Empty;

if (info.Parent != null)
{
    var pathToModule = info.Parent.FullName;
    pathToManager = Path.Combine(pathToModule,"Manager.exe").Replace(" ",string.Empty);
}

//工作良好

var fileInfo = new FileInfo(pathToManager);
var managerSeparator = new ToolStripSeparator()
{
    Visible = _manager.Visible = fileInfo.Exists // true
};

//无法工作

var managerSeparator = new ToolStripSeparator()
{
    Visible = _manager.Visible = File.Exists(pathToManager ) // false
};

谢谢!


1
对于 Windows 系统,文件路径应该使用 \\ 而不是 /,并且... 那你的示例调用使用了不同的路径...? - crashmstr
4
如果你之后还会使用FileInfo对象,我可以想象只有在这种情况下才需要使用FileInfo.Exist而不是File.Exists。 - Richard Priddy
2
你是否按照描述使用了“ProgramFiles(x86)”?因为这个文件夹名字包含空格“Program Files (x86)”。 - cichy
2
哦,这是我的错误。我使用了Assembly.GetExecutingAssembly().Location然后组合路径(Path.Combine(pathToModule,"Manager.exe")). 所以斜杠应该是正确的。 - Baranovskiy Dmitry
2
你尝试过这个吗: bool fileExists = File.Exists(@"C:\Program Files (x86)\MyAppFolder\Manager.exe");? - Richard Priddy
显示剩余2条评论
6个回答

34

这是唯一的区别,它与 FileInfo 的性质更相关:

FileInfo fileInfo = new FileInfo("myFile.txt"); // non-existent file
Console.WriteLine(fileInfo.Exists);             // false
File.Create("myFile.txt");
Console.WriteLine(File.Exists("myFile.txt"));   // true
Console.WriteLine(fileInfo.Exists);             // false

正如你所看到的,第一次使用fileInfo.Exists时,它的值会被缓存。

除此之外,在幕后它们做的事情是相同的。


10
实际上,这是一种行为上的重要差异!从表面上看,我相信大多数人会认为成功或失败取决于文件的当前状态,而不是该文件的某个缓存状态。 - ouflak
@ouflak 是的,这绝对会发生 - David Sherret

18

这两种方法没有区别,它们都使用.NET Framework内部的相同辅助方法。你可以通过反编译器或参考源代码看到这一点,该辅助方法的名称是File.FillAttributeInfo()。

在.NET Framework中有这样的重复是相当不寻常的,拥有多种完成同一任务的方式并不是一个好事情。但是,File类很特殊,它是在.NET 1.0发布时进行可用性研究后添加的。测试对象只能使用基本的BCL类(例如FileStream和FileInfo),而其他方面只能使用MSDN文档。测试结果并不好,因此添加了File类以帮助程序员轻松编写非常基本的文件操作代码,例如File.Exists()和File.ReadAllLines()。

所以这与类无关,只是你错误地使用了它们,比如没有实际使用相同的路径。请注意不要过度使用正斜杠,将其映射为反斜杠发生在Windows内部,并且在其他代码中实现不一致。使用//肯定不能达到你希望的效果。


看起来我要疯了,但是现在我重启VS后(同样的代码)无法再现这个问题。我们的软件中发现了这个问题作为一个bug,并且有一种非常奇怪的复现方式,实际上,当你第一次启动应用程序时一切都很好,但是在操作系统重新启动后会出现“文件未找到!”的情况。我可以在软件上稳定地复现这个问题。无论如何,我同意- File.Exists()和.Exist属性是相同的东西,问题出在其他地方。谢谢! - Baranovskiy Dmitry
注意:根据 https://dev59.com/kGEh5IYBdhLWcg3ww11p#22046285 的说法,存在差异...即在调用 File.Exists(myFilePath) 时会检查当前状态;而在第一次调用 myFileInfo.Exists 时才会被调用;然后对于每个后续的调用都返回相同的值,即使底层文件系统的状态已更改(即文件已创建或删除)。 - JohnLBevan

2

File.Exists()new FileInfo().Exists在完整路径(目录名+文件名)很长时的行为差异:

var f = @"C:\Program Files (x86)\MyAppFolder\many_subfolders\manager.exe";

//f.length > 260 characters

bool fileExists = File.Exists(f); //return false, even if the file exists

// Throw exception: "The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters."
bool fileInfoExists = new FileInfo(f).Exists;

2

我刚发现这个线程并想更新一下,因为我遇到了FileInfo与File.Exists之间的问题。

让我们来看一个场景,我们创建一个文件信息对象,用于一个当前不存在于UNC共享中的文件。

bool fileInfo  = new FileInfo(@"\\uncshare\name\filename.txt");

此时,该文件不存在,但如果我使用其他工具(其他代码或我的应用程序之外的工具)创建它,然后执行以下操作...

fileInfo.Refresh();
bool exists = fileInfo.Exists;

结果是假的,尽管它存在,fileInfo也被刷新了。

要得到正确的结果需要...

bool exists = File.Exists(f);

希望这能帮助其他人。

1

我使用以下Linqpad脚本复制了您的情景

var f = @"C:\Program Files (x86)\MyAppFolder\manager.exe";

bool fileExists = File.Exists(f);
bool fileInfoExists = new FileInfo(f).Exists;

fileExists.Dump();
fileInfoExists.Dump();

无论文件是否存在,我都运行了这个命令,并且每次都产生相同的输出。也许你可以在你的系统上尝试一下,看看是否仍然存在差异。

1
在您的第一个案例中,文件路径不正确,您需要在"Program Files (x86)"中添加空格。
其次,Path.Combine将返回目录路径,因此您最终会得到类似于"C:\Program Files (x86)\MyAppFolder\Manager.exe\"的东西,所以这是一个糟糕的想法。
两种方法的工作方式相同,因此请确保检查路径是否正确。

2
我从未见过你在“其次”段落中描述的问题。你能否举个例子,在最后一个Path.Combine参数中没有显式地使用“\”? - Andrew Morton

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