【发布时间】:2019-06-17 09:09:15
【问题描述】:
我想刷新一个文件输出流 (fstream)。如果我按照通常的方式 (flush()) 执行此操作,程序不会等到文件的内容被实际写入,它会继续执行。为了说明这个问题,请考虑以下场景:
A 要求 B 向文件写入内容。 B 完成任务后立即返回。然后,A 访问该文件。不幸的是,在操作系统实际设法写入文件内容之前,B 已经完成。文件还不存在,A 崩溃了。
那么,有没有类似阻塞刷新的东西?
请注意,当 B 写入 cout 并且 B 的 stdout 被重定向到文件时,不会出现此问题。不幸的是,如果 B 将 cout 用于其他目的,则无法应用此解决方法。
编辑:我发现问题最终出在其他地方。对于那些感兴趣的人:
简短的版本是,该文件确实存在,但由于另一个程序仍在写入该文件而无法读取。
长版:假设我们收到程序 A,它可以被认为是某个算法问题的“解决方案”。问题是在线的,这意味着输入必须以小块的形式提供给 A。为此,我们创建了一个与 A 通信的程序 B。每当 A 发送答案时,B 都会发送下一个输入块。我们在 A 和 B 之间进行交互:我们创建一个 FIFO 文件 (mkfifo fifo),然后创建 A < fifo | B > fifo。
我们想要捕获 A 的输出并查看它是否与某个目标输出文件 target.out 匹配。一种方法是让 B 打开一个文件流 (fstream fout("test.out", fstream::out)) 并将它从 A 读取的所有内容写入那里。另一个解决方案是:A < fifo | tee test.out | B > fifo。 A 和 B 交互完成后,我们运行diff test.out target.out 进行比较。
不幸的是,这两种解决方案都存在以下问题:一旦 A 完成,我们立即继续进行比较。 tee 或B,以test.out 的作者为准,尚未完成。如果是这样,则无法读取该文件(即使它存在,正如你们中的许多人所指出的那样)。
不考虑切换 A 和 B 的顺序,因为我们也在捕获 A 的返回码。 (必须报告解决方案在崩溃时已经崩溃。)
【问题讨论】:
-
你的解释不是很清楚(对我来说)。显然B调用Flush时文件存在。请添加一些说明问题的代码。
-
这是什么操作系统?通常,操作系统的文件系统有一个集成的缓冲层,因此即使数据还没有物理存储在磁盘上,另一个试图读取文件的程序仍然会“看到”它,因为文件系统驱动程序的读取例程知道查看文件系统的内存-在查看磁盘之前缓存。
-
这是在linux上的,我没有在其他操作系统上测试过。
-
您描述的场景不存在。如果 A 访问 B 应该写入的文件,即使该文件在磁盘上尚不存在,它也会成功。