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

huangapple go评论64阅读模式
英文:

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

问题

以下是代码的中文翻译部分:

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

我的sample.txt文件:

adsfasdfasdfasfasfasfasdfasfasfasfas
asdfasdfasdfasdfasfadsfsadfadsfsafad

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

英文:

Here is the code:

#define _CRT_SECURE_NO_WARNINGS

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

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

	if (fp == NULL)
		return 1;

	int error = 0;

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

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

My sample.txt file:

adsfasdfasdfasfasfasfasdfasfasfasfas
asdfasdfasdfasdfasfadsfsadfadsfsafad

In the above program fseek return -1 and makes the file blank and same with "w+" mode. The same program works in "r+" correctly. I want to know what is the relation between fseek and file modes in C language? I try to search but I found nothing on the web till now.

答案1

得分: 3

The fopen modes "w" and "w+" will delete the content of the file, if it exists, so that you will have a new file with a length of zero. The mode "r+" will not do this, but will keep any existing file content.

All of this is stated in the documentation for fopen.

If the file has a length of zero, then the function call

fseek(fp, -5, SEEK_END)

will fail, because there is no such offset.

Also, it is also worth noting that according to §7.21.9.2 ¶4 of the ISO C11 standard, that function call to fseek will invoke undefined behavior. When a file is opened in text mode (as you have done), the only permissible offset for fseek is the value 0 or the previous return value of a function call to ftell. This is especially a problem on Microsoft Windows, because it uses \r\n at the end of every line, which gets translated to \n in text mode. However, this is not a problem on POSIX platforms which do not distinguish between text mode and binary mode. POSIX platforms always use \n in both modes.

This rule is also mentioned in the documentation for fseek.

However, in practice, it probably won't be a problem to use fseek with a non-zero offset in text mode, as long as you don't jump into the offset between a \r and an \n character, and if you take into account that on Windows, a \r\n line ending counts as two offsets, even though \r\n gets translated to \n in text mode.

英文:

The fopen modes &quot;w&quot; and &quot;w+&quot; will delete the content of the fle, if it exists, so that you will have a new file with a length of zero. The mode &quot;r+&quot; will not do this, but will keep any existing file content.

All of this is stated in the documentation for fopen.

If the file has a length of zero, then the function call

fseek(fp, -5, SEEK_END)

will fail, because there is no such offset.

Also, it is also worth noting that according to §7.21.9.2 ¶4 of the ISO C11 standard, that function call to fseek will invoke undefined behavior. When a file is opened in text mode (as you have done), the only permissible offset for fseek is the value 0 or the previous return value of a function call to ftell. This is especially a problem on Microsoft Windows, because it uses \r\n at the end of every line, which gets translated to \n in text mode. However, this is not a problem on POSIX platforms which do not distinguish between text mode and binary mode. POSIX platforms always use \n in both modes.

This rule is also mentioned in the documentation for fseek.

However, in practice, it probably won't be a problem to use fseek with a non-zero offset in text mode, as long as you don't jump into the offset between a \r and an \n character, and if you take into account that on Windows, a \r\n line ending counts as two offsets, even though \r\n gets translated to \n in text mode.

答案2

得分: 1

Replace printf("Error fseek failed: %d\n", error); with perror("fseek"); and it'll likely print fseek: Invalid argument or similar.

You truncate the file by opening it with "w" and then try to go back 5 characters from the end (in an empty file). In a normal file, that can't be done.

When opening it with "r+", the content of the file is preserved, and seeking backward 5 steps from the end succeeds (with the content you've shown).

英文:

Replace printf(&quot;Error fseek failed: %d\n&quot;, error); with perror(&quot;fseek&quot;); and it'll likely print fseek: Invalid argument or similar.

You truncate the file by opening it with &quot;w&quot; and they try to go back 5 characters from the end (in an empty file). In a normal file, that can't be done.

When opening it with &quot;r+&quot; the content of the file is preserved and seeking backwards from the end 5 steps succeeds (with the content you've shown).

huangapple
  • 本文由 发表于 2023年5月20日 23:01:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/76295865.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定