C 覆盖文件中的一行
我试图覆盖文件中只包含未签名长数字的行。 文件的内容如下所示:C 覆盖文件中的一行,c,C,我试图覆盖文件中只包含未签名长数字的行。 文件的内容如下所示: 1 2 3 4 5 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"
1
2
3
4
5
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
我想用数字0替换特定的数字。我编写的代码如下所示:
1
2
3
4
5
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
程序的输出如下所示:
1
2
3
4
5
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
有趣的是,如果我对文件进行cat,它看起来如下所示:
1
2
3
4
5
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
显示的缺失行?我可以复制并修复
目前的问题是,当您在r+
中打开一个文件时,必须在每次从读取切换到写入以及从写入切换到读取时调用fseek
在这里,您可以在写入0
之前正确地调用fseek
,但在写入和读取之后调用not。文件指针未正确定位,您将获得未定义的行为
修复很简单,只需更换:
if(times == 3)
{
fseek(f, pos, SEEK_SET);
fprintf(f, "%lu\n", 0);
}
与
但是要当心:它在这里起作用,因为你用一条长度完全相同的线替换一条线。如果您试图将包含1000的行替换为包含0的行,那么在windows系统中,如果行尾为\r\n
,那么在类unix系统中,如果行尾为\n
,则会得到一个包含0
的额外行
因为下面是将会发生的情况(Windows案例):
重写之前:
... 1 0 0 0 \r \n ...
之后:
... 0 \r \n 0 \r \n ...
因为顺序文件是。。。一系列连续的字节 在我看来,更改文本文件最合适的方法是创建一个新的临时文件,逐行复制旧文件,进行任何需要的更改,删除旧文件(或重命名)并重命名临时文件
差不多
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");
当然,您需要验证真实代码中的所有调用。从
fscanf
@user3666471中删除\n
,它似乎输出良好;我看到的唯一问题是fprintf(f,“%lu\n”,0)
应该使用int
或者fprintf(f,“%d\n”,0)代码>long pos=0代码>,fprintf(f,“%lu\n”,0UL);(f)
问题是3
是一个字符长,而10
是两个字符长。该文件是…2\n3\n4\n5…
,现在是…2\n10\n\n5…
,因为3\n4
已被10\n
@francis>取代。但目标是用一个0
覆盖一个3
。在这一点上,我认为最好打开一个新文件,并在那里做我想要的更改。在文件中“就地”进行更改是一大罐蠕虫。@user3666471是的!就地替换的唯一用例是具有固定长度记录的(通常为二进制)文件,您可以对其进行随机访问。