覆盖文件中的一行

时间:2015-04-26 08:10:04

标签: c

我正在尝试覆盖只包含无符号长号的文件中的一行。 该文件的内容如下所示:

1
2
3
4
5

我想用数字0替换一个特定的数字。我写的代码如下:

FILE *f = fopen("timestamps", "r+");

unsigned long times = 0;
int pos = 0;
while(fscanf(f, "%lu\n", &times) != 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", &times) != EOF)
{
    printf("%lu\n", times);
    times = 0;
}
fclose(f);

程序的输出如下:

1
2
10
5

有趣的是,如果我捕获文件,它看起来像这样:

1
2
10

5

我在ftell犯了错误吗?另外,为什么printf没有显示cat显示的缺失行?

2 个答案:

答案 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");

当然,您需要使用实际代码验证所有呼叫。