我正在尝试覆盖只包含无符号长号的文件中的一行。 该文件的内容如下所示:
1
2
3
4
5
我想用数字0替换一个特定的数字。我写的代码如下:
FILE *f = fopen("timestamps", "r+");
unsigned long times = 0;
int pos = 0;
while(fscanf(f, "%lu\n", ×) != EOF)
{
if(times == 3)
{
fseek(f, pos, SEEK_SET);
fprintf(f, "%lu\n", 0);
}
times = 0;
pos = ftell(f);
}
fclose(f);
f = fopen("timestamps", "r");
times = 0;
while(fscanf(f, "%lu\n", ×) != EOF)
{
printf("%lu\n", times);
times = 0;
}
fclose(f);
程序的输出如下:
1
2
10
5
有趣的是,如果我捕获文件,它看起来像这样:
1
2
10
5
我在ftell
犯了错误吗?另外,为什么printf
没有显示cat
显示的缺失行?
答案 0 :(得分:2)
我可以重现并修复。
目前的问题是,当您在r+
中打开文件时,必须每次从阅读切换到写入以及从写入到阅读时都会调用fseek
。< / p>
在此,您在撰写fseek
之前正确拨打0
,但在写入之后而不是,请阅读以下内容。文件指针未正确定位,您将获得未定义的行为。
修复很简单,只需替换:
if(times == 3)
{
fseek(f, pos, SEEK_SET);
fprintf(f, "%lu\n", 0);
}
带
if(times == 3)
{
fseek(f, pos, SEEK_SET);
fprintf(f, "%lu\n", 0);
pos = ftell(f);
fseek(f, pos, SEEK_SET);
}
但是 BEWARE :它在这里工作,因为你用一条完全相同长度的线替换一条线。如果您尝试将包含1000的行替换为包含0的行,则会在Windows系统上获得包含0
的额外行,其中行尾为\r\n
,而00
位于unix上具有行尾\n
的系统。
因为这是会发生的事情(Windows案例):
重写之前:
... 1 0 0 0 \r \n ...
之后:
... 0 \r \n 0 \r \n ...
因为顺序文件是......一个连续的字节系列!
答案 1 :(得分:0)
更改文本文件的最舒服的方法是创建一个新的临时文件,逐行复制旧文件,随意更改,删除旧文件(或重命名)并重命名临时文件文件。
像
这样的东西char line[1000];
FILE *original, *temporar;
original = fopen("original", "r");
temporar = fopen("temporar", "w");
while (fgets(line, sizeof line, original)) {
processline(line);
fprintf(temporar, "%s", line);
}
fclose(temporar);
fclose(original);
unlink("original"); // or rename("original", "original.bak");
rename("temporar", "original");
当然,您需要使用实际代码验证所有呼叫。