当文件被不同的进程删除时,文件流会发生什么?

What happens to a filestream when the file is deleted by a different process?

在 C# 中,我用 FileShare.Delete 打开一个文件。这允许我打开文件而不限制其他进程删除它。例如:

using (FileStream fs = new FileStream(@"C:\temp.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete))
{
    int len = (int)fs.Length;
    byte[] array = new byte[len];
    int bytesRead = fs.Read(array, 0, len);
}

我的问题是:

  1. 如果文件在我们创建流之后但在我们读取它之前被另一个进程删除,会发生什么情况?操作系统是否会在 stream\handle 关闭之前保留文件的副本?
  2. 我可以依靠读取已删除的文件而不会出现任何错误或内容错误吗?

是的,另一个进程可以删除该文件,但您不会得到任何异常,因为已创建指向磁盘上文件的指针,因此您的进程将继续读取,但是当您重试打开流时,您将得到一个异常因为文件系统中的条目不存在

这里有一个完整的例子来重现你的案例

尝试执行此操作并转到资源管理器并删除您的文件

 class Program
    {
        static void Main(string[] args)
        {
            for (int i = 0; i < 10000; i++)
            {
                File.AppendAllText(@"c:\temp.txt", Guid.NewGuid().ToString());  
            }
            //read the file 
            using (FileStream fs = new FileStream(@"C:\temp.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete))
            {
                while (fs.CanRead)
                {
                    //here I read a chunk of 1000 bytes to let stream open 
                    int len = 1000;
                    Thread.Sleep(1000);
                    byte[] array = new byte[len];
                    int bytesRead = fs.Read(array, 0, len);
                }
            }

        }
    }

文件被标记为删除,但在最后一个打开的句柄关闭之前实际上删除,如documentation for DeleteFile.[=11中所述=]

请注意,您无法打开标记为删除的文件的新句柄,但该文件仍会出现在目录列表中,并且在实际删除之前不能被同名文件替换。这与 Unix 系统不同,在 Unix 系统中文件会立即从目录中消失("unlinked")。正如 Ben 在评论中所建议的那样,您可以通过重命名 and/or 在删除文件之前移动文件来解决此问题。

此外,正如 MoonRabbit 指出的那样,您可以 "delete" 使用资源管理器打开文件,但那是因为那样只会将文件移动到回收站。用于立即删除文件的 Shift+Delete 选项将不起作用。