写入有限行数到文本文件的算法

5

我有一个程序,需要经常将文本行写入日志文件。我希望限制日志文件中的行数为1000行。当我向文件写入行时,它应该正常地追加它们。一旦文件达到1000行,我想删除第一行,然后追加新行。是否有一种方法可以在不每次重写整个文件的情况下完成这个操作?


1
计数器和MOD运算符? - Pol0nium
需要每行刷新还是可以写入临时缓冲区? - jrok
2
只要为每行分配固定大小,就可以将文件转换为循环缓冲区。将第一行作为当前写入索引,然后在此之后,使所有其他行具有某个宽度。当达到所需的最大值时,只需返回索引0即可。 - Scott Mermelstein
如果可以的话,我建议采取不同的策略。在写入日志之前,检查文件大小并且如果超过阈值,则“滚动日志”会更加健壮 - 将当前日志移动到log._old1,将log._old1移动到log_old2等,直到您想要保存的日志数量为止。(请注意,如果这样做,实际上是从底部开始 - _old4到_old5,_old3到_old4,_old2到_old3,_old1到_old2,current到_old1,然后创建一个新的current。)您甚至可以有一个单独的任务来处理文件滚动。 - Scott Mermelstein
@ScottMermelstein 谢谢你的建议。我现在正在实现一个循环缓冲区。然后只有在需要时才会写入日志。如果你想把它作为答案发布,我会标记它为已接受。 - Janz Dott
@user2848097 谢谢,我已经发布了。 - Scott Mermelstein
5个回答

1
通常情况下,对于像这样的情况,最好一次性从开头删除多行。
也就是说,如果您的限制是1000行,而且达到了1000行,请删除前300行左右,然后继续编写。这样做的好处是,您不需要每写一行就执行删除操作,而是每隔300次才进行一次删除操作。如果您需要保留1000行,则可以保留多达1300行,并在达到1300行时删除300行。

1

所有文件都必须对齐到FS簇大小。因此,没有办法删除第一行而不重写文件。您可以将一行追加到文件中,但无法删除第一行。

您可以轮流使用2个文件。 或者在内存中使用一些缓冲区并定期刷新它。


1
我认为您仍然需要扫描文件,以了解文件中此时有多少行。在这种情况下,您可以将其放入某种缓冲区中,以便您可以轻松添加和删除。然后进行日志记录,完成后,您可以使用缓冲区(或仅最后1000行)“重新编写”文件。其他替代方案已在上面讨论过。是的,请尽量避免逐行删除。通常,这是一项昂贵的操作。
我在这里和CodeProject上找到了一些类似的话题: 小型记录器类; 使用C ++标准流的灵活记录器类

http://www.codeproject.com/Articles/584794/Simple-logger-for-Cplusplus

希望您会发现它们有用 :)

0

当您只想使用一个文件,而且行的长度不是固定的时候,没有办法不重写整个文件。

根据您向文件添加内容的频率,我认为没有任何问题。大约1000行,每行100个字符,只有大约100kb,这并不太多。此外,您可以添加一些迟滞。

然而:

  • 如果行长是恒定的(或者您将行长硬限制为某个常量),则可以覆盖最旧的行。但是,您必须跟踪旧/新行的日志文件位置
  • 我会使用两个文件:第一个文件用于追加行。当文件已满时,将其重命名为第二个文件,并从开头填充第一个文件。

0

每当您想要记录日志时,您可以打开文件,读取您的写入索引,跳转到该位置,并编写固定宽度的日志条目。当您的索引达到上限时,只需将其设置回0。

然而,这样做有很多警告 - 首先是每个正确的日志条目(假设您在中间关闭文件)都需要打开、读取、查找、写入、查找、写入和关闭 - 找到您的索引,转到它,写入新条目,然后更新您的索引。您还有编写固定大小数据元素的固有问题。此外,人类读者将依赖于您的内容来知道文件的“开头”。大多数人期望“第1行”是第一行。

我更支持只有几个文件并且“滚动”它们,以便每个文件本身都是连贯的,但如果您只想要一个具有固定行数的文件,则循环缓冲区的想法可以起作用。


@user2848097,我认为你对如何提高效率有更好的想法,但如果我的帖子能帮到你,我很高兴。 - Scott Mermelstein
我将每行文本保存在循环缓冲区中。我跟踪最后一个索引,并使用它来确定写入文件的顺序。即使有1000行,它也非常高效。谢谢! - Janz Dott

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接