1

对于一个特定的作业,我正在使用标准 C 下的顺序文件实现一个基本的数据存储系统,它一次不能加载超过 1 条记录。因此,基本部分是创建一个新文件,其中存储了我们对原始记录所做的任何事情的结果。前一个文件已重命名,并在工作名称下创建一个新文件。该代码在 Windows 7 上使用 MinGW 5.1.6 编译。

问题是,这个特定版本的代码(我的函数周围有几乎相同的版本)并不总是删除旧文件,因此重命名失败,因此存储的数据被 fopen() .

FILE *archivo, *antiguo;

remove("IndiceNecesidades.old");  // This randomly fails to work in time.
rename("IndiceNecesidades.dat", "IndiceNecesidades.old"); // So rename() fails.

antiguo = fopen("IndiceNecesidades.old", "rb");
// But apparently it still gets deleted, since this turns out null (and I never find the .old in my working folder after the program's done).
archivo = fopen("IndiceNecesidades.dat", "wb"); // And here the data gets wiped.

基本上,只要 .old 以前存在,就有可能没有及时删除它,以便 rename() 成功生效。内部和外部都没有可能的名称冲突。

奇怪的是它只适用于这个特定的文件。除了名称更改为 Necesidades.dat (发生在 3 个不同的函数中)之外,相同的片段工作得很好。

// I'm yet to see this snippet fail.
FILE *antiguo, *archivo;

remove("Necesidades.old");
rename("Necesidades.dat", "Necesidades.old");

antiguo = fopen("Necesidades.old", "rb");
archivo = fopen("Necesidades.dat", "wb");

关于为什么会发生这种情况的任何想法,和/或如何确保 remove() 命令在执行 rename() 时生效?(我想只要 fopen() 返回一个非空指针,就只使用一个 while 循环来强制调用 remove() ,但这听起来像是因为删除请求或其他东西溢出操作系统而乞求崩溃。)

4

3 回答 3

3

所以突然,在阅读了斯科特提到的权限之后,我想到了“权限被拒绝”并应用了一些谷歌。事实证明,这是一个很常见的错误,即使是晦涩的错误。 caf 是对的,它在另一段代码中。即,我忘记在用于显示内容的函数中关闭同一个文件。由于我没有跟踪那个特定的细节,它似乎是随机的。

免责声明:每周的数学作业只需要很少的睡眠时间。¬¬

于 2010-04-13T04:36:19.547 回答
1

这听起来很奇怪,当您说相同的代码使用不同的文件名可以正常工作时更是如此 - 我强烈怀疑您的代码中的其他地方存在错误。但是,您应该能够通过重命名要删除的文件来解决它:

rename("IndiceNecesidades.old", "IndiceNecesidades.older");
remove("IndiceNecesidades.older");
rename("IndiceNecesidades.dat", "IndiceNecesidades.old");
于 2010-04-13T03:45:48.777 回答
1

remove()检查函数是否有错误可能是个好主意。man remove表示函数0在成功和-1失败时返回,设置errno记录错误。尝试用

if (remove("IndiceNecesidades.old") != 0){
   perror("remove(\"IndiceNecesidades.old\") failed");
}

这应该给出一条错误消息,说明失败的原因。

此外,似乎不需要删除

人重命名()

rename() 系统调用导致名为 old 的链接被重命名为 new。如果 new 存在,则首先将其删除。old 和 new 都必须是同一类型(即,两者都必须是目录或非目录)并且必须驻留在同一文件系统上。

rename() 系统调用保证 new 的实例将始终存在,即使系统在操作过程中崩溃。

如果 old 的最后一个组件是符号链接,则符号链接被重命名,而不是它指向的文件或目录。

如果出现以下情况,EPERM 将被退回:

[EPERM] 包含 old 的目录被标记为粘性,并且包含目录和 old 都不属于有效用户 ID。

[EPERM] 新文件存在,包含 new 的目录被标记为粘性,并且包含目录和 new 都不属于有效用户 ID。

所以下一步是检查您对包含目录的权限

于 2010-04-13T03:37:37.193 回答