通过随机重命名覆盖Windows中的文件失败

时间:2012-06-13 19:04:21

标签: c windows file edit overwrite

我有一个文本文件,我想通过将其重写为临时文件来编辑,然后覆盖原始文件。此代码不会这样做,因为它已经简化,但确实包含了我遇到的问题。在Windows上,当重命名功能失败时,EXAMPLE.TXT文件将在一个看似随机的运行次数后消失。我不知道为什么,但到目前为止它在Linux上运行良好。为什么会发生这种情况,如何在完全不同的方向上解决它,例如在不重命名的情况下从程序中覆盖原始文件?

此外,还有哪些更好的方法?这种方法在Windows上有其他缺陷,例如在调用remove之后但在重命名之前用户关闭的程序,这在Linux上不会出现问题(在删除删除之后)?

#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);
  }
}

2 个答案:

答案 0 :(得分:3)

这样做确实可能会造成麻烦。您的代码在Windows上有四种可能的结果:

  • 删除正常,重命名工作,没问题
  • 删除正常,但另一个进程打开文件并删除共享。常见于恶意软件扫描程序和文件内容索引器。这可确保在文件的最后一个句柄关闭时实际删除文件。问题是,重命名失败,因为文件仍然存在
  • 不会删除,因为文件被锁定,您的断言触发
  • 什么都没发生,因为在构建发布版本时,assert()是一个无操作。

最后一个子弹的好几率,它肯定解释了可重复的失败。你需要一个更具防御性的策略来处理第二个问题:

  • 删除filename.bak,如果失败则报告错误
  • 将fileName重命名为filename.bak,如果失败则报告错误
  • 将tempName重命名为filename,报告错误,如果失败则重命名filename.back
  • 删除filename.bak,不报告错误

这是一个常见的场景,winapi具有它的功能,ReplaceFile()。请务必使用备份文件选项以获得最大的收益。   -

答案 1 :(得分:0)

有时,防病毒软件会在不方便的时刻扫描文件,从而导致出现此类问题。

如果remove失败,请尝试短暂休眠,然后重试。