英文:
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 <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;
}
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 "w"
and "w+"
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 "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.
答案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("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 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 "r+"
the content of the file is preserved and seeking backwards from the end 5 steps succeeds (with the content you've shown).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论