c# - File.Exists 在 File.Delete 之后返回 true
问题描述
我有以下方法来删除具有提供路径的文件
private void DestroyFile(string path)
{
try
{
if (File.Exists(path))
{
File.Delete(path);
}
if (File.Exists(path))
{
throw new IOException(string.Format("Failed to delete file: '{0}'.", path));
}
}
catch (Exception ex)
{
throw ex;
}
}
如果文件在 File.Delete 方法之后存在,我将收到抛出的 IOException。具体来说
System.IO.IOException):无法删除文件:'C:\Windows\TEMP\[FILE NAME]'。
我还确认执行完成后路径变量中的位置不存在该文件。我想知道我是否在 File.Delete 之后更新文件系统和使用 File.Exists 再次检查它之间遇到竞争条件。有没有更好的方法可以顺利删除?我知道如果文件不存在, File.Delete 不会返回错误,所以这些检查可能有点多余。我应该检查文件是否正在使用而不是它是否存在?
一些重要的附加信息:该程序可以并且确实经常成功运行,但最近经常看到此特定错误。
解决方案
File.Delete
将文件标记为删除。只有当文件的所有句柄都关闭时,文件才会真正被删除(如果没有这样的句柄 - 在 File.Delete 返回后它总是会被删除)。正如DeleteFile winapi 函数(由 C# 使用File.Delete
)所记录的:
DeleteFile 函数将文件标记为在关闭时删除。因此,文件删除直到文件的最后一个句柄关闭后才会发生
通常,您删除的文件没有打开的句柄。或者,如果有打开的句柄——它们通常没有“删除”共享(这个共享允许另一个进程将文件标记为删除),所以当你尝试删除这样的文件时——它要么被删除(没有打开的句柄)要么访问被拒绝或类似的异常被抛出(一些句柄,但没有删除共享)。
但是,有时某些软件(例如防病毒软件或搜索索引器)可能会通过“删除”共享打开任意文件并将它们保留一段时间。如果您尝试删除此类文件 - 它不会出错,并且当该软件关闭其句柄时文件确实会被删除。但是,File.Exists
对于此类“待删除”文件将返回 true。
您可以使用这个简单的程序重现此问题:
public class Program {
public static void Main() {
string path = @"G:\tmp\so\tmp.file";
// create file with delete share and don't close handle
var file = new FileStream(path, FileMode.Create, FileAccess.ReadWrite, FileShare.Delete);
DestroyFile(path);
GC.KeepAlive(file);
}
private static void DestroyFile(string path) {
try {
if (File.Exists(path)) {
// no error
File.Delete(path);
}
// but still exists
if (File.Exists(path)) {
throw new IOException(string.Format("Failed to delete file: '{0}'.", path));
}
}
catch (Exception ex) {
throw ex;
}
}
}
您可以File.Exists
在上面的程序中永远重试检查 - 文件将一直存在,直到您关闭句柄。
所以这就是你的情况 - 一些程序已经打开了这个文件的句柄FileShare.Delete
。
你应该预料到这种情况。例如 - 只需删除该File.Exists
检查,因为您将文件标记为删除,无论如何它都会被删除。
推荐阅读
- python - Python问题中的滚动窗口数据集
- javascript - Pressable 和 TouchableOpacity 的区别
- pandas - 大熊猫的分组总和
- node.js - 未显示 Azure Web 应用程序/虚拟目录上的节点应用程序
- if-statement - 在eclipse中反转if语句
- java - 没有为 log4j2 的 Appender AchLog 问题提供名称属性
- python - Google Cloud PubSub 在异步拉取消息时抛出 504 Deadline Exceeded 错误
- python - 使用 Python2 与 Python3 进行 Base64 URL 解码
- css - 滚动捕捉类型接近使用哪个捕捉点?
- c++ - 尝试将 lambda 函数放入队列时出现一般分配器错误(可能与 unique_ptr 相关)