我想知道在完成文件写入后,是应该使用Write::flush
还是File::sync_all
。
File
时使用File::sync_all
。请注意,这并非必需。
File
的 Write::flush
实现使用操作系统相关的 flush
操作,例如 std::sys::unix::File::flush
或者 std::sys::windows::File::flush
。这些 flush
操作实际上什么也不做。两种实现都只返回 Ok(())
。
为什么?因为在两种情况下,write()
已经使用了底层的系统调用 write()
;Windows 上是基于句柄的写入,Unix-like 系统上是基于文件描述符的写入。此时,它已经超出了 Rust 环境的范畴,只剩下一个特定于文件的系统调用。
Write::flush
有用的呢?如果你有任何类型的缓冲区在实际文件之前,例如BufWriter
,它就很有用。如果你有一个由BufWriter
包装的File
,那么你需要使用flush
来确保字节被写入文件。虽然记住BufWriter
的Drop
实现也尝试(!)写入这些字节很有用,但它可能会或可能不会工作,所以你应该在那里调用Write::flush
(请参阅BufWriter
的文档)。sync_all
并不是必需的,反而会阻塞程序。操作系统将处理文件系统同步。虽然你可以通过sync_data
或sync_all
等待同步发生,但通常最好不要这样做。sync_all()
的作用,他们几乎肯定不想在写出随机文件后调用它。sync_all()
并不能确保文件已经被写入底层硬件(操作系统会自动完成这个任务),它只会让你的程序_等待_直到完成。这只在非常特殊的情况下才需要使用。 - user4815162342Write::flush
实际上是一个无操作(no-op)[source]。对于File
来说是没有用的,只是为了保持一致性而实现。而这个接口是专门为那些在写入目标之前使用应用级别内存缓冲区的流设计的,正如文档中所述:
刷新此输出流,确保所有中间缓冲内容都到达它们的目标。
File::sync_data
是File
有用版本的flush
。在底层,内部缓冲区是在内核级别使用的,sync_data
会委托给fdatasync
POSIX调用,这就是flush
在应用级别所做的事情。
File::sync_all
的作用类似于File::sync_data
,并且还确保文件的元数据被写入磁盘。它在 POSIX 系统上委托给fsync
。File::sync_data
和 File::sync_all
的实现可能完全相同。
sync_all()
的作用,那么几乎肯定不应该调用它,这只会减慢程序的速度而没有任何好处。(它的使用案例是实现具有精确数据耐久性保证的软件,如日志数据库。) 如果您在实际写入过程中使用了缓冲写入器,那么在写入结束时需要执行flush()
操作。Bufwriter 通常会在关闭时执行flush()
,但这样无法报告错误,因此最好显式地执行flush()
。 - user4815162342