如何确保在关闭 fstream 之前将数据写入磁盘?

发布于 2024-12-06 07:52:08 字数 243 浏览 1 评论 0原文

下面的内容看起来很合理,但我听说即使在 close() 调用之后,数据理论上仍然可以位于缓冲区中而不是磁盘上。

#include <fstream>

int main()
{
    ofstream fsi("test.txt");

    fsi << "Hello World";

    fsi.flush();

    fsi.close();

    return 0;
}

The following looks sensible, but I've heard that the data could theoretically still be in a buffer rather than on the disk, even after the close() call.

#include <fstream>

int main()
{
    ofstream fsi("test.txt");

    fsi << "Hello World";

    fsi.flush();

    fsi.close();

    return 0;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

是伱的 2024-12-13 07:52:08

您无法使用标准工具来实现此目的,并且必须依赖操作系统设施。
对于 POSIX fsync 应该是您所需要的。由于无法从标准流中获取 C 文件描述符,因此您必须在整个应用程序中求助于 C 流,或者只是打开文件以刷新磁盘。或者,还有sync,但这会刷新所有缓冲区,这是您的用户和其他应用程序会讨厌的。

You cannot to this with standard tools and have to rely on OS facilities.
For POSIX fsync should be what you need. As there is no way to a get C file descriptor from a standard stream you would have to resort to C streams in your whole application or just open the file for flushing do disk. Alternatively there is sync but this flushes all buffers, which your users and other applications are going to hate.

執念 2024-12-13 07:52:08

您可以通过刷新流来保证缓冲区中的数据写入磁盘。这可以通过调用其 flush() 成员函数、flush 操纵器、endl 操纵器来完成。

但是,在您的情况下不需要这样做,因为 close 保证将任何挂起的输出序列写入物理文件。

第 27.9.1.4 / 6 条:

basic_filebuf< charT, 特征 >* close();

效果:如果 is_open() == false,则返回空指针。如果放置区域存在,则调用overflow(traits::eof())来刷新字符。 (...)

You could guarantee the data from the buffer is written to disk by flushing the stream. That could be done by calling its flush() member function, the flush manipulator, the endl manipulator.

However, there is no need to do so in your case since close guarantees that any pending output sequence is written to the physical file.

§ 27.9.1.4 / 6:

basic_filebuf< charT, traits >* close();

Effects: If is_open() == false, returns a null pointer. If a put area exists, calls overflow(traits::eof()) to flush characters. (...)

薄情伤 2024-12-13 07:52:08

您使用哪个操作系统?

您需要使用直接(非缓冲)I/O 来保证数据直接写入物理设备,而不会触及文件系统写入缓存。请注意,在进行物理写入之前,它仍然必须通过磁盘缓存。

在 Windows 上,打开文件时可以使用 FILE_FLAG_WRITE_THROUGH 标志。

Which operating system are you using?

You need to use Direct (non-buffered) I/O to guarantee the data is written directly to the physical device without hitting the filesystem write-cache. Be aware it still has to pass thru the disk cache before getting physically written.

On Windows, you can use the FILE_FLAG_WRITE_THROUGH flag when opening the file.

屌丝范 2024-12-13 07:52:08

§ 27.9.1.4
basic_filebuf* close();
效果:如果 is_open() == false,则返回空指针。 如果放置区域
存在,调用overflow(traits::eof())来刷新字符。
如果最后一个
在 *this 上调用的虚拟成员函数(下溢、上溢、
eekoff 和eekpos)溢出然后调用a_codecvt.unshift
(可能几次)以确定终止序列,插入
这些字符并再次调用overflow(traits::eof())。最后,
无论前面的任何调用是否失败或抛出异常
异常,该函数关闭文件(就像通过调用
std::fclose(文件))。如果该函数进行任何调用,
包括 std::fclose 都会失败,close 会因返回空指针而失败。
如果这些调用之一抛出异常,则该异常将被捕获并
关闭文件后重新抛出。

它保证刷新文件。但是,请注意,操作系统可能会对其进行缓存,并且操作系统可能不会立即刷新它。

§ 27.9.1.4
basic_filebuf* close();
Effects: If is_open() == false, returns a null pointer. If a put area
exists, calls overflow(traits::eof()) to flush characters.
If the last
virtual member function called on *this (between underflow, overflow,
seekoff, and seekpos) was overflow then calls a_codecvt.unshift
(possibly several times) to determine a termination sequence, inserts
those characters and calls overflow(traits::eof()) again. Finally,
regardless of whether any of the preceding calls fails or throws an
exception, the function closes the file (as if by calling
std::fclose(file)). If any of the calls made by the function,
including std::fclose, fails, close fails by returning a null pointer.
If one of these calls throws an exception, the exception is caught and
rethrown after closing the file.

It's guaranteed to flush the file. However, note that the OS might keep it cached, and the OS might not flush it immmediately.

放手` 2024-12-13 07:52:08

我很确定调用 close() 的全部目的是刷新缓冲区。 本网站同意。尽管取决于您的文件系统和挂载设置,但仅仅因为您已“写入磁盘”并不意味着您的文件系统驱动程序和磁盘硬件实际上已获取数据并在物理金属上制作了磁性位。它可能仍然在磁盘缓冲区中。

I'm pretty sure the whole point of calling close() is to flush the buffer. This site agrees. Although depending on your file system and mount settings, just because you've 'written to the disk' doesn't mean that your file system drivers and disk hardware have actually taken the data and made magnet-y bits on the physical piece of metal. It could probably be in a disk buffer still.

醉殇 2024-12-13 07:52:08

close() 成员函数关闭底层操作系统文件描述符。此时,该文件应该位于磁盘上。

The close() member function closes the underlying OS file descriptor. At that point, the file should be on disk.

时常饿 2024-12-13 07:52:08

关闭前如何刷新

How abt flushing before closing?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文