当文件被其他进程删除时,文件流会发生什么?

时间:2016-10-10 08:36:18

标签: c# .net windows filestream

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

using (FileStream fs = new FileStream(@"C:\temp\1.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. 如果文件在我们创建流后被其他进程删除,但在我们阅读之前会发生什么?在关闭流\句柄之前,操作系统是否保留文件的副本?
  2. 我可以依赖于阅读已删除的文件而不会收到任何错误或错误的内容吗?

2 个答案:

答案 0 :(得分:6)

该文件被标记为删除,但在最后一个打开的句柄关闭之前,实际已被删除,如documentation for DeleteFile中所述。

请注意,您无法打开标记为删除的文件的新句柄,但该文件仍将显示在目录列表中,并且在实际删除之前不能替换为同名文件。这与Unix系统不同,在Unix系统中文件立即从目录中消失(“未链接”)。正如Ben在评论中建议的那样,你可以通过重命名和/或移动文件来解决这个问题。

另外,正如MoonRabbit指出的那样,你可以使用资源管理器“删除”一个打开的文件,但这只是因为它只将文件移动到回收站。立即删除文件的Shift + Delete选项无效。

答案 1 :(得分:0)

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

这是一个重现案例的完整示例

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

 class Program
    {
        static void Main(string[] args)
        {
            for (int i = 0; i < 10000; i++)
            {
                File.AppendAllText(@"c:\temp\1.txt", Guid.NewGuid().ToString());  
            }
            //read the file 
            using (FileStream fs = new FileStream(@"C:\temp\1.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);
                }
            }

        }
    }