2

I am trying to save a backup of some data. If the backup exists then I want to delete it, give the most recent file the name of the backup file, and then save the new file as the most recent file.

The problem I am running into is that when I delete an existing file I still cannot save another file under the same name. The system still thinks that the file exists, and indeed the file isn't deleted at the point where the program throws the exception even though the two lines are right after each other. The only thing I can think of is that that the "delete" operation hasn't had time to complete by the time the move operation wants to execute. But I do not know how to fix it.

The code looks something like this.

 File.Delete(filePath.Substring(filePath.Length - 4) + ".bak");
 File.Move(filePath, filePath.Substring(0, filePath.Length - 4) + ".bak");

I thought of setting a timer in order to execute the move function later, but it seems to me that this would probably be a very sloppy and dangerous way of handling the problem. In addition, the amount of time that one needs to wait might have to vary from system to system. So I am thinking that there must be a better way.

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
Popinjay
  • 73
  • 1
  • 7
  • 6
    I feel that the Filepath is not proper in File.Delete method. Can you check if the path is correct? – Baskar Rao Nov 30 '15 at 19:41
  • 3
    Try moving the file first and then deleting the latest file from the original location http://stackoverflow.com/questions/5704982/file-move-fails-when-preceded-by-a-file-delete – keyboardP Nov 30 '15 at 19:45

2 Answers2

2

The problem has probably to do with the fact that you use two different .Substring methods: String#Substring(int) and String#Substring(int,int). Indeed:

File.Delete(filePath.Substring(filePath.Length - 4) + ".bak");
//                   ^ with one int
File.Move(filePath, filePath.Substring(0, filePath.Length - 4) + ".bak");
//                           ^ with two ints

And unfortunately, the two are not semantically equivalent. The one with one int is the start index. So given that filePath is equal to test.txt, the file you aim to remove is .txt.bak and next you aim to move a file to test.bak. Or running this with Mono's C# emulator:

csharp> String filePath = "test.txt";
csharp> filePath.Substring(filePath.Length - 4) + ".bak"
".txt.bak"
csharp> filePath.Substring(0, filePath.Length - 4) + ".bak"
"test.bak"

Please update it with:

File.Delete(filePath.Substring(0,filePath.Length - 4) + ".bak");
//                   ^ added zero
File.Move(filePath, filePath.Substring(0, filePath.Length - 4) + ".bak");

Another more elegant and less error prone way is evidently to use a variable in between such that you are sure, you are talking about the same file:

String backupfile = filePath.Substring(0, filePath.Length - 4) + ".bak";
File.Delete(backupfile);
File.Move(filePath,backupfile);

Finally it's not recommended to do path processing yourself: use dedicated methods to join and manipulate file paths.

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
1

I tried your code with a little change and it worked fine. I only changed how you defined the backup file name, because the file extension can be more or less than 3 chars:

string backupPath = Path.GetFileNameWithoutExtension(filePath) + ".bak";
File.Delete(backupPath);
File.Move(filePath, backupPath);

But if it does not work for you, try to rename the backup to lets say "*.bak2" and then delete that one.

Hope that helps...

Dieter Meemken
  • 1,937
  • 2
  • 17
  • 22