我找不到任何关于在使用fprintf
或fwrite
写入文件时是否已经隐式完成缓冲的信息。我知道这可能是实现/平台相关的功能。我感兴趣的是,我是否可以期望它至少在Windows,Linux或Mac OS X等现代流行平台上有效实现?
AFAIK,通常 I/O 例程的缓冲在 2 个级别上完成:
- 库
- 级别:可以是C标准库,也可以是Java SDK(
BufferedOutputStream
)等; - 操作系统级别:现代平台广泛缓存/缓冲 I/O 操作。
我的问题是关于#1,而不是#2(因为我知道这已经是真的)。换句话说,我是否可以期望所有现代平台的 C 标准库实现都利用缓冲?
如果没有,那么手动创建一个缓冲区(具有巧妙选择的大小)并在溢出时刷新它是解决问题的好方法吗?
结论
感谢所有指出setbuf
和setvbuf
等功能的人。这些是我一直在寻找的确切证据来回答我的问题。有用的摘录:
所有文件都使用默认分配的缓冲区(完全缓冲)打开 如果已知它们不是指交互式设备。此函数 可用于设置要用作缓冲区的特定内存块 或禁用流的缓冲。
默认情况下,默认流
stdin
和stdout
完全缓冲,如果 众所周知,它们不是指交互式设备。否则,他们 默认情况下可以是行缓冲的,也可以是无缓冲的,具体取决于 系统和库实现。stderr
也是如此,它 默认情况下始终为行缓冲或未缓冲。
stdio 例程的缓冲会进行调整,以与相关操作系统的典型块大小保持一致。这样做是为了在默认情况下优化 I/O 操作的数量。当然,您可以随时使用setbuf()/setvbuf()
例程来更改它。
除非您正在做一些特殊的事情,否则您应该坚持使用默认缓冲,因为您可以非常确定它在您的操作系统上是最佳的(对于典型场景)。
唯一证明这一点的情况是,当您想使用 stdio 库与不适合它的 I/O 通道进行交互时,在这种情况下,您可能希望完全禁用缓冲。但我不会经常看到这种情况。
您可以放心地假设标准 I/O 在任何现代系统上都得到了合理的缓冲。
正如@David所说,您可以期待合理的缓冲(在两个级别)。
然而,fprintf
和fwrite
之间可能存在巨大的差异,因为fprintf
解释格式字符串。如果你堆叠采样,你会发现很大一部分时间将双精度转换为字符串,以及类似的东西。
C IO 库允许使用 setvbuf
控制缓冲完成的方式(在应用程序内部,在操作系统执行的操作之前)。 如果您没有指定任何内容,则标准要求"打开时,流被完全缓冲当且仅当可以确定它不是",该要求也适用于stdin
和stdout
,而即使可以检测到它被定向到非交互式设备,stderr
也不会缓冲。