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

标签 c windows file edit overwrite

我有一个文本文件,我想通过将其重写为临时文件然后覆盖原始文件来进行编辑。这段代码没有这样做,因为它被简化了,但它确实包含了我遇到的问题。在 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);
  }
}

最佳答案

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

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

顺便说一句,最后一颗子弹的概率很高,这当然可以解释可重复的失败。你需要一个更具防御性的策略来处理第二颗子弹:

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

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

关于c - 通过随机重命名覆盖 Windows 中的文件失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11021639/

相关文章:

c - 为什么我不能在 C 中传递的函数内打印数组的大小?

c - 扫描: "%[^,]s"与 "%[^,],s"

python - 使用区域设置打印以色列货币

c# - 使用 DMA 进行文件内数据复制

file - 即时创建 zip 文件以通过 node.js 下载

c++ - ifstream.open() 不打开文件

c - 将 Imagemagic C 库与 anjuta 一起使用

c - 在 c 中使用 sscanf 的正则表达式忽略空格

c# - 从 Windows 服务启动 Windows 应用程序

windows - 单击编译按钮时 Inno Script Studio 无限期挂起