我有一个程序,它接收用户给出的数据(int,浮点数和字符串)并将其写入文本文件。现在我必须更新该部分写入的数据。
例如:
在文件的第4行,我想更改前2个单词(有int
和float
)。我怎样才能做到这一点?
根据我发现的信息,可以使用fseek()
和fputs()
,但我不确切知道如何到达特定的行。
(解释的代码将被赞赏,因为我是C的首发)
答案 0 :(得分:4)
您无法在文件中“插入”字符。你必须创建程序,它将读取整个文件,然后在插入新文件,你的版本,文件的其余部分之前复制部分。
答案 1 :(得分:1)
您确实需要阅读所有文件,并忽略不需要的内容。
fseek
并不是很有用:它将文件定位在某个字节偏移处(相对于文件的开头或结尾)并且不知道行边界。
实际上,文件中的行是一个定义不明确的概念。通常,行是由换行符('\n'
)结束的字节序列(与换行符不同)。某些操作系统(Windows,MacOSX)以特殊方式读取文本文件(例如,真实文件包含\r\n
以结束每一行,但C库会让您觉得您已阅读\n
)。
在实践中,您可能希望line input routines使用getline
(或者fgets
)。
如果你使用getline
,你应该关心free
- 行缓冲区。
如果您的文本文件具有非常规则的结构,则可以fscanf
数据(忽略您需要跳过的内容)而不关心行边界。
如果你想绝对使用fseek
(这是一个错误),你必须阅读两次文件:第一次记住每行开始(或结束)的位置,第二次记住{{ 1}}到行开始。但是,这不适用于更新,因为您无法在文件中间插入字节。
实际上,最昂贵的操作是实际的磁盘读取。缓冲(部分由内核和fseek
函数完成,部分由你在处理行时完成)可以忽略不计。
当然,您无法在文件中更改某些行。如果您需要这样做,请处理文件以进行输入,生成一些输出文件(包含修改后的输入)并在完成后重命名。
顺便说一句,您可能对GDBM等索引文件感兴趣,甚至对SqlLite,MariaDb,mongodb等数据库感兴趣....您可能对标准文本序列化格式感兴趣,例如JSON或YAML(两者都有许多库,即使是C,也可以处理它们)。答案 2 :(得分:0)
fseek()
用于随机访问文件,其中每个数据记录具有相同的大小。通常,数据是二进制的,而不是文本。
要解决您的特定问题,您需要一次读取一行以查找要更改的行。进行更改的一个简单解决方案是将这些行写入临时文件,将更改写入同一临时文件,然后跳过要更改的原始文件中的部分,并将重置复制到临时文件。最后,关闭原始文件,将临时文件复制到该文件,然后删除临时文件。
话虽如此,我建议您了解有关随机访问文件的更多信息。当存储所有相同大小的记录时,这些非常有用。如果您可以控制创建orignal文件,那么这些文件可能更适合您当前的目的。