如何取消创建文件

Ian*_*oyd 2 error-handling file-io winapi

我们假设我正在将数据写入文件句柄:

hFile = CreateFile(filename, GENERICREAD | GENERICWRITE, 0, null, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
//[snip error check]
try
{
   if (!WriteFile(hFile, buffer, count, ref bytesWritten, null))
       throw new Win32Exception(GetLastError());
}
finally
{
   CloseHandle();
}
Run Code Online (Sandbox Code Playgroud)

如果我的数据写入失败,我希望在关闭句柄时删除该文件.即:我希望文件是"un-CreatFile'd".


我已经尝试了显而易见的,如果出现问题则删除文件:

hFile = CreateFile(filename, GENERICREAD | GENERICWRITE, 0, null, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
//[snip error check]
try
{
   try
   {
      if (!WriteFile(hFile, buffer, count, ref bytesWritten, null))
          throw new Win32Exception(GetLastError());
   }
   finally
   {
      CloseHandle();
   }
}
catch
{
   DeleteFile(filename);
   throw;
}
Run Code Online (Sandbox Code Playgroud)

这种方法存在两个问题:

  1. 有一个竞争条件,有人可以在关闭它之后打开我的文件,但在我删除它之前
  2. 我可能有权创建文件,但不能删除它.

我想要的是一种追溯指定的方法:

FILE_FLAG_DELETE_ON_CLOSE:文件将在其所有句柄关闭后立即删除,其中包括指定的句柄和任何其他打开或重复的句柄.

到我打开的文件.

我创建了文件!当然我可以解开它!所有这些都是因为我忘了事前指定一面旗帜?

Nik*_*hil 5

在Windows Vista及更高版本中,可以使用SetFileInformationByHandle和完成FILE_DISPOSITION_INFO.


Ben*_*igt 5

在所有版本的Windows中,您都可以

  1. FILE_SHARE_DELETE最初打开文件时指定.
  2. 再次打开它,指定 FILE_FLAG_DELETE_ON_CLOSE
  3. 关闭第二个手柄.
  4. 关闭所有句柄后,将删除该文件.

FILE_FLAG_DELETE_ON_CLOSE在文档中的说明中进行了解释CreateFile:

关闭所有句柄后立即删除该文件,其中包括指定的句柄和任何其他打开或重复的句柄.如果文件存在打开的句柄,则调用将失败,除非它们都是以FILE_SHARE_DELETE共享模式打开的.


如果自动删除不够好,您可以查看Transactional NTFS,将文件创建和所有写入放入事务,然后在必要时将其回滚.