fseek 在“w”模式下返回 -1,并在 C 程序中使文件为空

fseek is returning -1 in "w" mode and making file blank in C program

提问人:Rakesh Solanki 提问时间:5/20/2023 更新时间:5/20/2023 访问量:61

问:

代码如下:

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char* argv[])
{
    FILE* fp = fopen("sample.txt", "w");

    if (fp == NULL)
        return 1;

    int error = 0;

    if ((error = fseek(fp, -5, SEEK_END)) != 0)
    {
        printf("Error fseek failed: %d\n", error);
        fclose(fp);
        return 1;
    }

    fprintf(fp, "%d", 1);
    fclose(fp);
    return 0;
}

我的示例 .txt 文件:

adsfasdfasdfasfasfasfasdfasfasfasfas
asdfasdfasdfasdfasfadsfsadfadsfsafad

在上面的程序中,fseek 返回 -1 并使文件为空,并且与“w+”模式相同。相同的程序在“r+”中正常工作。我想知道 C 语言中的 fseek 和 file 模式之间有什么关系?我尝试搜索,但直到现在我在网上什么也没找到。

C 文件-IO fseek

评论


答:

3赞 Andreas Wenzel 5/20/2023 #1

模式,并将删除 fle 的内容(如果存在),以便您将拥有一个长度为零的新文件。该模式不会执行此操作,但会保留任何现有文件内容。fopen"w""w+""r+"

所有这些都在 的文档中进行了说明。fopen

如果文件的长度为零,则函数调用

fseek(fp, -5, SEEK_END)

会失败,因为没有这样的偏移量。

此外,还值得注意的是,根据 ISO C11 标准的 §7.21.9.2 ¶4,该函数调用将调用未定义的行为。当文件以文本模式打开时(如您所做),唯一允许的偏移量是对 ftell 的函数调用的值或上一个返回值。这在Microsoft Windows上尤其是一个问题,因为它在每行的末尾使用,以文本模式转换为文本模式。但是,这在不区分文本模式和二进制模式的 POSIX 平台上不是问题。POSIX平台始终在两种模式下使用。fseekfseek0\r\n\n\n

此规则在 的文档中也有提及。fseek

但是,在实践中,在文本模式下使用非零偏移量可能不是问题,只要您不跳转到 a 和字符之间的偏移量,并且如果您考虑到这一点,在 Windows 上,一行结尾算作两个偏移量,即使在文本模式下被翻译为。fseek\r\n\r\n\r\n\n

评论

0赞 Rakesh Solanki 5/20/2023
当我的重点是 fseek 时,我完全忘记了,mode 将在处理后立即创建新文件。你已经解决了我关于这个问题的大部分问题。我仍然想知道文件模式和.谢谢。ww+fopenfseek
0赞 Andreas Wenzel 5/20/2023
@RakeshSolanki:您可以在所有模式下使用。但是,有一定的规则。我已经在我的回答中提到了一条规则。另一个规则是,当一个文件在更新模式下打开时(即该模式包含一个,例如),那么你可能不得不在读取后在写入之前使用(或其他文件定位功能),反之亦然。有关该规则的详细信息,请参阅此问题fseekfopen+"r+"fseek
1赞 Ted Lyngmo 5/20/2023 #2

替换为 它可能会打印或类似。printf("Error fseek failed: %d\n", error);perror("fseek");fseek: Invalid argument

您通过打开文件来截断文件,然后他们尝试从末尾返回 5 个字符(在空文件中)。在普通文件中,这是无法做到的。"w"

当打开它时,文件的内容被保留,并且从末尾向后查找时,5 个步骤会成功(使用您显示的内容)。"r+"

评论

1赞 Rakesh Solanki 5/20/2023
是的,我抓住了我的错误。它返回“fseek: Invalid argument”。谢谢。