我在程序中生成了一个大约有2000行文本的文件,每一行都有员工的信息,输出方式如下
1 1 Isaac Fonseca 58 c 1600 1310.40 6 1 0.22 2164.80 1
2 1 Manuel Gutierrez 22 d 1700 1523.37 4 1 0.13 897.26 1
3 1 Daniel Bernal 34 c 1600 1195.84 2 1 0.26 836.16 1
4 1 Miguel Gonzalez 43 e 1800 1195.84 0 1 0.15 0.00 1
但每当我编辑员工信息时,我都必须更新文件,我正在做的是搜索行并尝试重写
我看到了以下有同样问题的人的问题,但当我试图写入文件时,它总是写入文件的末尾
是否覆盖文本文件上的特定行?
这是我的代码:
datos = fopen(archivo,"a+");
for(i=0;i<num;i++){
// buscar la linea
fgets(lineaA,100,datos);
// sobreescribir
if(i == (num-1))
cursor = ftell(datos);
}
cursor -= strlen(lineaA) - 1;
fseek(datos,cursor,SEEK_CUR);
fputs(linea2,datos);
fclose(datos);
你几乎不能做到这一点。
可以使用fseek
转到文件中的特定位置,也可以将数据写入该位置(可能需要使用"r+"
模式)。
但文件通常存储为字节(或字符)序列,而不是行序列。
如果您小心地写入与行中已经写入的字节数完全相同的字节数,您可能会侥幸逃脱惩罚——但在您的示例中,行的长度各不相同,因此这不是一个选项。
例如,你可以用空格填充每一行,这样它们的长度都相同,但如果你使用普通的文本编辑器修改文件,很容易破坏布局。
对于文本文件,通常的方法是将文件读入内存,修改内存中的表示,然后重新创建整个文件。您可能想将内容写入一个新的临时文件,然后在确认没有写入错误后对其进行重命名。
这就是文本编辑器通常所做的
(不要太担心效率;2000行并没有那么大,你也不会注意到写它们所需的时间。)
还有其他选择。您可以定义具有固定长度记录的二进制格式,也可以使用数据库。或者,您可以将新行附加到文件中,并将重复的视为已删除(但如果进行大量更新,这可能会导致文件变得非常大)。
除非这类似于家庭作业,需要自己滚动所有代码,否则切换到数据库可能是最容易的。考虑到剩下的代码都在工作,SQLite可能是最明显的选择。
如果你真的想坚持(至少类似于)你当前的格式和代码,我可能会把每一行的数据填充到64或128个字节(如果你有一些更长的记录,请隔离它们,比如把它们全部移到文件的末尾,或者把它们放在一个单独的文件中)。这种方式(大多数?)可以在不影响其他行的情况下进行编辑。如果你有员工的行索引,你也可以直接查找该行,而不是读取它的所有前一行来查找它。
您使用选项"a+"打开文件,该选项只允许追加到文件,而不允许覆盖。您想使用"r+"
datos = fopen(archivo,"r+);