我有一个需要更改的配置文件。
文件的结构是:
resolution 12x34
interval 1234
所以两个字符串带有空格分隔符。我用来改变它的代码是:
FILE *fp = fopen(configuration_file, "a+");
char str[100], key[100], value[100];
if(fp) {
while(fgets(str, 100, fp) != NULL) {
if(2 == sscanf(str, "%s %s", &key, &value)) {
if(strcmp(key, "resolution") == 0){
if(msg->resolution){
fprintf(fp, "%s %s\r\n", key, msg->resolution);
}
} else if(strcmp(key, "interval") == 0) {
if(msg->interval) {
fprintf(fp, "%s %d\r\n", key, msg->interval);
}
} else {
fputs(str, fp);
}
} else {
fputs(str, fp);
}
}
} else {
(void)printf("-- Configuration file not found (%s)\r\n --", configuration_file);
}
fclose(fp);
想法是逐行阅读。根据{{1}}的文档说它在新行停止。对每行进行字符串扫描并将其解析为键和值。到目前为止这么好,按预期行事。然后将新行打印到文件中,覆盖刚刚扫描的行。这就是问题所在。如果我使用fgets
,则只处理第一个值,即分辨率。结果是:
fprintf
它会覆盖错误的行并完全跳过第二行。
如果我删除resolution oldxres
resolution newxres
而只是打印它找到的值,它会按照预期打印。
我在这里缺少什么? fprintf
是否推送文件指针?
答案 0 :(得分:2)
然后将新行打印到文件中,覆盖刚刚扫描的行。
文件无法正常工作。写入新文件。完成后,将新文件重命名为旧名称。或者,将整个文件读入内存,更改内存中的内容,然后将其写回。
如果修改的行永远不会比原始行更长,则可以重写单个行。否则,修改后的行将溢出您尚未阅读的下一行,并将其销毁。为了防止这种情况,你需要某种前瞻缓冲区,这太麻烦且容易出错。在最糟糕的情况下,无论如何你都需要阅读整个文件。