1

我打算用 C++ 读取一个文件。读取本身发生在一个while循环中,并且正在从一个文件中读取。

当函数从文件中读取信息时,它会将这些信息推送到系统中的某个位置。问题是这个文件可能会在循环进行时发生变化。

我怎样才能在文件中捕捉到新信息?我尝试std::ifstream在我的计算机上手动读取和更改我的文件,因为无限循环(sleep(2)每个循环之间都有一个)正在进行,但正如预期的那样 - 没有发生任何事情。

编辑:文件将在每个新的数据条目到文件时覆盖自身。

帮助?

在虚拟机 Ubuntu Linux 12.04 上运行,如果这可能是有用的信息。这不是家庭作业。

4

4 回答 4

1

通常的解决方案类似于 MichaelH 提出的方案:写入过程以附加模式打开文件,并始终写入到末尾。阅读过程符合 MichaelH 的建议。

这适用于每次运行中的少量数据。如果进程应该运行很长时间,并生成大量数据,文件最终会变得太大,因为它也包含所有处理过的数据。在这种情况下,解决方案是使用一个目录,在其中生成编号文件,每个数据记录一个文件。写入过程将每个数据集写入一个新文件(递增数字),读取过程将尝试打开新文件,并在完成后将其删除。这比第一个建议复杂得多,但即使对于每秒生成大量数据并运行多年的进程也有效。

编辑:

OP 后来的评论说该设备实际上是一个 FIFO。在这种情况下:

  • 你不能寻求,所以 MichaelH 的建议不能按字面意思使用,但是

  • 您无需查找,因为数据在被读取时会自动从 FIFO 中删除,并且

  • 根据数据的大小和写入方式,写入可能是原子的,因此您不必担心部分记录,即使您恰好在写入中间读取。

关于后者:确保读取和写入缓冲区都足够大以包含完整的记录,并且写入器在每条记录后刷新。并确保记录小于保证原子性所需的大小。(从历史上看,在我知道的早期 Unix 上,这是 4096,但如果从那以后它没有增加,我会感到惊讶。虽然......在 Posix 下,这是由 定义的PIPE_BUF,只能保证至少为 512,在现代 Linux 下只有 4096。)

于 2013-07-08T11:59:27.623 回答
0

您可以使用inotify来监视文件更改。如果您需要更简单的解决方案 - 读取文件属性(使用 stat(),并检查文件的 last_write_time)。

但是,您仍然可能会错过一些文件修改,同时您将打开和重新读取文件。因此,如果您可以控制写入文件的应用程序,我建议您使用其他东西在这些进程之间进行通信,例如管道。

于 2013-07-08T11:53:12.333 回答
0

只需读取文件,重命名文件,打开重命名的文件。对系统进行数据处理,并在循环结束时关闭文件。睡眠后,重新打开白色循环顶部的文件,重命名并重复。

这是解决问题的最简单方法,并且不必在处理阶段编写代码来处理对文件的动态更改。

为了绝对确保您没有损坏,最好重命名文件。这保证了来自另一个进程的任何更改都不会影响处理。可能没有必要这样做 - 这取决于处理和文件的更新方式。但这是一种更安全的方法。移动或重命名操作保证是原子的——所以如果使用这种方法应该不会有并发问题。

于 2013-07-08T11:10:56.317 回答
0

更明确地说,如果你想要类似尾巴的行为,你会想要:

  1. 打开文件,读入数据。保存长度。关闭文件。
  2. 稍等一下。
  3. 再次打开文件,尝试寻找到最后读取位置,读取剩余数据,关闭。
  4. 冲洗并重复
于 2013-07-08T11:12:55.887 回答