Overwriting files in Windows by renaming randomly fails

时光总嘲笑我的痴心妄想 提交于 2019-12-13 01:32:29

问题


I have a text file that I want to edit by rewriting it to a temp file and then overwrite the original. This code doesn't do that as it's simplified but it does include the problem I have. On Windows the EXAMPLE.TXT file will disappear after a seemly random number of runs when the rename function fails. I don't know why but so far it has worked fine on Linux. Why does this happen and how can I solve it going in an entirety different direction, such as overwriting the original file from within the program without renaming?

Furthermore, what other, better methods exist? This method has other flaws on Windows, such as the program being closed by a user just after remove is called but before rename, which would not be a problem on Linux (after getting rid of remove)?

#include <stdio.h>
#include <assert.h>

int main(int argc, char *argv[]) {
  unsigned int i=0;
  FILE *fileStream, *tempStream;
  char fileName[] = "EXAMPLE.TXT";
  char *tempName = tmpnam(NULL);

  while(1) {
     printf("%u\n",i++);
     assert(fileStream = fopen(fileName, "r+"));
     assert(tempStream = fopen(tempName, "w"));

     fprintf(tempStream,"LINE\n");
     fflush(tempStream); /* fclose alone is enough on linux, but windows will sometimes not fully flush when closing! */

     assert(fclose(tempStream) == 0);
     assert(fclose(fileStream) == 0);
     assert(remove(fileName) == 0); /* windows fails if the file already exists, linux overwrites */
     assert(rename(tempName,fileName) == 0);
  }
}

回答1:


Sometimes antivirus software can cause such a problem by scanning a file at an inconvenient moment.

If the remove fails, try sleeping for a short time and then retrying.




回答2:


Doing it this way is indeed likely to cause trouble. There are four possible outcomes of your code on Windows:

  • deletes fine, rename works, no problem
  • deletes fine, but another process had the file open with delete sharing. Common for malware scanners and file content indexers. Which ensures that the file actually gets deleted when the last handle on the file is closed. Problem is, the rename fails because the file still exists
  • doesn't delete because the file is locked, your assert fires
  • nothing at all happens because assert() is a no-op when you build the release version.

Good odds for the last bullet btw, it certainly explains repeatable failure. You'll need a more defensive strategy to deal with the 2nd bullet:

  • delete filename.bak, report error if that failed
  • rename fileName to filename.bak, report error if that failed
  • rename tempName to filename, report error and rename filename.back back if that failed
  • delete filename.bak, don't report error

This is such a common scenario that the winapi has a function for it, ReplaceFile(). Be sure to use the backup file option for maximum bang for the buck. -



来源:https://stackoverflow.com/questions/11021639/overwriting-files-in-windows-by-renaming-randomly-fails

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!