13

After removing a file using the system.io.file class:

System.IO.File.Delete(openedPdfs.path);

I need to run some code if the file was sucessfully deleted. As long as the method does not return any value, I am checking if the file exist after the delete method. If it still exist I supposed the operation had failed.

The problem is, the deletion method works fine, but there is a couple of seconds to the file to be deleted. The Exist function return true because at the time it is checking the file is there.

How can I verify for sure if the System.IO.File.Delete(openedPdfs.path); completed successfully?

Code:

FileInfo file = new FileInfo(openedPdfs.path);    
System.IO.File.Delete(openedPdfs.path);
if (file.Exists == false)
{ ... }
else 
{ ... }
Cœur
  • 37,241
  • 25
  • 195
  • 267
Guilherme Longo
  • 2,278
  • 7
  • 44
  • 64
  • 1
    "The most elegant way I can think of is using a [FileSystemWatcher](http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.aspx) and subscribe to its `Deleted` event." http://stackoverflow.com/questions/9370012/waiting-for-system-to-delete-file – Tim Schmelter Jan 04 '13 at 16:12
  • 3
    Are you concerned about the case when the delete is successful, but a new file of the same name is created before your check for existence? – HABO Jan 04 '13 at 16:12
  • @TimSchmelter FileSystemWatcher has been reported to drop events under load. Some have suggested that it may be used to improve responsiveness, but that they still poll at a reduced interval to be sure to not miss events. FSW may also drag down performance, especially if the filters are unnecessarily coarse. – Andrew Dennison Oct 21 '16 at 19:30

8 Answers8

12

As others have pointed out, the File.Delete method will throw an exception in case of failure.

What they omitted to say is that the exception will be thrown in almost all cases but not in all cases.

Specifically, the File.Delete method will not throw an exception if the file to be deleted did not happen to already exist.


  • If we look at the Official Microsoft Documentation for System.IO.File.Delete,
  • and if we skip past the list of exceptions thrown,
  • and if we keep scrolling to go past the extensive code example to arrive at a "Remarks" section,
  • and if the keep reading this section despite the trivialities that it mostly consists of, such as
    • "Specify a file name with any relative or absolute path"
    • and "Relative path information is interpreted as relative to the current working directory"
    • and "To obtain the current working directory, see GetCurrentDirectory"
  • then we arrive at the following little gem, hidden among the noise:

If the file to be deleted does not exist, no exception is thrown.

In other words, this function has deliberately built-in silent failure.

Silent failure constitutes sabotage against the developer in virtually all cases.

Mike Nakis
  • 56,297
  • 11
  • 110
  • 142
  • 1
    While not an MS apologist, I think the .NET design avoids throwing exceptions when in most cases the caller doesn't care how or when the file got deleted. Exceptions are not a very performant way of reporting a not very interesting result. Directory.Create follows the same pattern. Again it resolves the race condition by not reporting the prior existence of the directory. In most use cases, it does not matter. The WinAPI handles this by explicitly reporting exactly what did or did not happen in an integer return value without throwing a costly exception. – Andrew Dennison Oct 21 '16 at 19:44
  • The behavior of library functions should always be as consistent as possible regardless of "likely scenarios" and "most use cases". Otherwise, they constitute sabotage against every single programmer who is dealing with an unusual case. Having to deal with an unusual case is already hard enough as it is, we do not need library functions sabotaging us on top of that. – Mike Nakis Nov 24 '22 at 11:57
1

Delete should throw an exception if the file wasn't deleted. Hence, your call to Exists is redundant.

Have a look at the documentation for Delete.

Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
  • 3
    There is a slight delay from when File.Delete completes to when the file actually gets deleted. – tofutim Sep 19 '13 at 21:13
  • 16
    -1: Your first sentence is wrong. Delete doesn't throw when the file hadn't existed before (and hence is not deleted). Have a closer look at the documentation for Delete: "If the file to be deleted does not exist, no exception is thrown." – mkf Feb 20 '14 at 13:50
1

This is ancillary to Daniel A. White's answer: We can see the signature for the method is public static void Delete(string path). So clearly, you're not going to get feedback from the Delete call except by exception. But let's suppose you have a file that gets written or updated periodically by another process:

  1. Your program successfully delete the file.
  2. The other process recreates it immediately after the delete.
  3. Your program tests for existence with file.Exists. There's a new file with the same name, so that returns true. You're technically going down the wrong path.

This exact scenario might not be true for the problem you're currently trying to solve, but checking to see if the Delete call threw an exception is much more robust than relying on your current implementation.

Reacher Gilt
  • 1,813
  • 12
  • 26
0

It won't throw exception if file doesn't exists. In case of error it will throw exception if it couldn't be deleted, check File.Delete

Zbigniew
  • 27,184
  • 6
  • 59
  • 66
  • The documentation says "If the file to be deleted does not exist, no exception is thrown." – Moby Disk Jan 26 '15 at 20:54
  • @MobyDisk true, but I meant that it will throw exception in case of error. Technically deleting non existing file is not error. – Zbigniew Jan 27 '15 at 16:10
0

You can always use

 System.IO.File.Exists(path)

Although I agree with Daniel, if Delete does not throw exception you should be good.

Sebastian K
  • 6,235
  • 1
  • 43
  • 67
0

From the comments and suggestions you should be able to use the following to acheive your desired result

try {
  FileInfo file = new FileInfo(openedPdfs.path);    
  System.IO.File.Delete(openedPdfs.path);
  // if no exception is thrown then you should assume all has gone well and put  
  // your file successfully deleted code here.
} catch /*(Specfic exceptions can be referenced here in separate catch blocks see Daniel A. White answer)*/ {
  // If something bad happened and the file was not deleted put handling code here
} finally {
  // if some action needs to be taken regardless of whether the file was successfully deleted or not put 
  // that code here
}
Luke Baughan
  • 4,658
  • 3
  • 31
  • 54
0

I discovered that if you use the FileInfo Delete() instance method that the FileInfo instance property Exists is not updated.
For example the following code will throw a file not found exception because the file has been deleted but the second if (output_file.Exists) still evaluates to true.

FileInfo output_file;
if (output_file.Exists) output_file.Delete();   

FileStream fs;
if (output_file.Exists)
{
     fs = new FileStream(fi.FullName, FileMode.Open, FileAccess.ReadWrite);
}
else
{
     fs = new FileStream(fi.FullName, FileMode.CreateNew, FileAccess.ReadWrite);
}

I found that creating a new FileInfo from the old one fixed the problem:

FileInfo output_file;
if (output_file.Exists)
{
    output_file.Delete();
    output_file = new FileInfo(output_file.FullName);      
}

FileStream fs;
if (output_file.Exists)
{
     fs = new FileStream(fi.FullName, FileMode.Open, FileAccess.ReadWrite);
}
else
{
     fs = new FileStream(fi.FullName, FileMode.CreateNew, FileAccess.ReadWrite);
}
PiotrWolkowski
  • 8,408
  • 6
  • 48
  • 68
0
private String del(String fileLocation) {

 if (File.Exists(@fileLocation)) {
  try {
   File.Delete(@fileLocation);
  } catch (Exception e) {
   return "File couldn't be deleted because: " + e.GetType().Name;
  }
 } else {
  return "File doesn't exist";
 }

 return "File successfully deleted";
}
D.Snap
  • 1,704
  • 1
  • 22
  • 15