【问题标题】:Overwriting files in Windows by renaming randomly fails通过随机重命名覆盖 Windows 中的文件失败
【发布时间】:2012-06-16 19:26:07
【问题描述】:

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

此外,还有其他更好的方法吗?此方法在 Windows 上还有其他缺陷,例如程序在调用 remove 之后重命名之前被用户关闭,这在 Linux 上不会出现问题(摆脱 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);
  }
}

【问题讨论】:

    标签: c windows file edit overwrite


    【解决方案1】:

    这样做确实容易惹麻烦。您的代码在 Windows 上有四种可能的结果:

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

    顺便说一句,最后一个子弹的可能性很大,它肯定解释了可重复的失败。你需要一个更具防御性的策略来处理第二个子弹:

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

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

    【讨论】:

      【解决方案2】:

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

      如果remove 失败,请尝试休眠一小段时间,然后重试。

      【讨论】:

      • 我正在运行 MSE 并且确实禁用了实时保护,但它没有任何区别。 remove() 不幸的是没有失败(或者至少返回值没有表明它)。
      • 对不起,我的意思是rename,但同样的评论适用于两者。
      • 成功了!但是,我仍然对它失败的原因以及解决它的替代方法感兴趣,也许是更清洁的方法。
      猜你喜欢
      • 2019-02-18
      • 1970-01-01
      • 2019-03-24
      • 2013-05-14
      • 2011-12-26
      • 1970-01-01
      • 2016-12-08
      • 1970-01-01
      • 2011-05-26
      相关资源
      最近更新 更多