开发者

How do I properly open a file for deletion?

开发者 https://www.devze.com 2023-03-27 08:28 出处:网络
I thought this is a completely trivial task but it gave me some headache. I would like to open a file to ensure I got exclusive access, test for certain conditions, then delete it.

I thought this is a completely trivial task but it gave me some headache. I would like to open a file to ensure I got exclusive access, test for certain conditions, then delete it.

Right now I'm using a 99% approach:

FileStream s = null;
try {
    s = new FileStream (
        path,
        FileMode.Open,
        FileAccess.ReadWrite,
        FileShare.None);
    // some stuff about the file is checked here
    s.Dispose ();
    // hope the file is not accessed by someone else...
    File.Delete (path);
    return true;
}
catch (IOException) {
   开发者_开发问答 if (s !=null) s.Dispose ();
    return false;
}

This usually works, but I figured there'd be a better way that avoids the edge condition.

Opening the file with a DeleteOnClose flag does not work because said check (which occurs after opening with the deletion flag already set) might indicate that the file should not be deleted.


Something like this:

    using (FileStream file = new FileStream(path,
       FileMode.Open,
       FileAccess.ReadWrite,
       FileShare.Delete))
    {
        // you can read the file here and check your stuff
        File.Delete(path);
    }

PS: note the 'using' keyword. It allows you to have a cleaner code as it takes care of Dispose calls.


First of all, you're imitating "using" statement, and you're doing it the wrong way. You should Dispose the file stream just once, in the finally clause, not twice in try and catch. But, better use using.

using (FileStream s = new FileStream())
{
}

Second, you're best option is Transactional NTFS (one of the wrappers can be found in Nabu Library: https://dev.triflesoft.org/mercurial/nabu/), however Transactional NTFS is limited to NTFS and Windows Vista+, so if you need FAT16/FAT32 or Windows XP, this is not the way to go.


You can also try to move/rename opened file to disallow access by other processes, but this is limited to NTFS too AFAIR.


If you do not need a file to be deleted instantly, you can use Setup API's SetupQueueDelete function.


You can't totally prevent the possibility of the race condition. Considering that your program is in trouble if between the check and the delete the file gets modified there are at least 2 workarounds I can see:

  • Get a temp file name, rename the file to the tempfile, do the check and rename back if needed (could lead to new issues depending on your business logic)
  • You could set the readonly attribute on the file before you check it.
0

精彩评论

暂无评论...
验证码 换一张
取 消