以下是使用fflush()的示例代码:
#include <string.h>
#include <stdio.h>
#include <conio.h>
#include <io.h>
void flush(FILE *stream);
int main(void)
{
FILE *stream;
char msg[] = "This is a test";
/* create a file */
stream = fopen("DUMMY.FIL", "w");
/* write some data to the file */
fwrite(msg, strlen(msg), 1, stream);
clrscr();
printf("Press any key to flush DUMMY.FIL:");
getch();
/* flush the data to DUMMY.FIL without closing it */
flush(stream);
printf("\nFile was flushed, Press any key to quit:");
getch();
return 0;
}
void flush(FILE *stream)
{
int duphandle;
/* flush the stream's internal buffer */
fflush(stream);
/* make a duplicate file handle */
duphandle = dup(fileno(stream));
/* close the duplicate handle to flush the DOS buffer */
close(duphandle);
}
我对fflush()的了解是,它是一个用于刷新输出缓冲区的库函数。我想知道使用fflush()的基本目的是什么,我在哪里可以使用它。主要是我有兴趣了解使用fflush()会有什么问题。
答案 0 :(得分:45)
有点难以说出&#34;可能会出现问题&#34; (过度?)使用fflush
。根据您的目标和方法,可以<或>成为或成为问题的各种事物。可能更好的方式来看待这一点是fflush
的意图。
首先要考虑的是fflush
仅在输出流上定义。输出流收集要写入文件的内容&#34;进入一个大(ish)缓冲区,然后将该缓冲区写入该文件。这种收集和写作的要点是以两种方式提高速度/效率:
因此,提供您的C库及其stdio流实现的人会在您的操作系统上执行任何适当的操作,以找到合理最优的&#34;块大小,并将所有输出收集到该大小的块中。 (今天的数字4096,8192,16384和65536往往是好的,但它实际上取决于操作系统,有时也取决于底层文件系统。注意&#34;更大&#34;不是总是&#34;更好&#34;:一次以4千兆字节的数据流传输数据可能比以64千字节的数据块执行更差。)
但这会产生问题。假设您正在写一个文件,例如带有日期和时间戳和消息的日志文件,并且您的代码将在以后继续写入该文件,但是现在,它希望暂停一段时间并让日志分析器读取日志文件的当前内容。一种选择是使用fclose
关闭日志文件,然后fopen
再次打开它以便稍后添加更多数据。但是,将任何挂起的日志消息推送到底层操作系统文件,但保持文件打开会更有效。这是fflush
的作用。
缓冲还会产生另一个问题。假设你的代码有一些bug,它有时会崩溃,但你不确定它是否会崩溃。并且假设您已经写了一些内容,此数据输出到底层文件系统非常重要。在调用可能崩溃的潜在错误代码之前,您可以调用fflush
将数据推送到操作系统。 (有时这对调试很有用。)
或者,假设您使用的是类Unix系统,并进行fork
系统调用。此调用会复制整个用户空间(复制原始进程)。 stdio缓冲区位于用户空间中,因此克隆在fork
调用时具有与原始进程相同的缓冲但尚未写入的数据。同样,解决问题的一种方法是在执行fflush
之前使用fork
将缓冲的数据推出。如果一切都在fork
之前,那就没有什么可复制的了;新鲜的克隆不会尝试写入缓冲的数据,因为它不再存在。
您添加的fflush
越多,您就越能打败收集大量数据的原始想法。也就是说,你正在做出权衡:大块更有效率,但是会引起一些其他问题,所以你做出决定:&#34;在这里效率较低,解决比单纯效率更重要的问题&#34;。你拨打fflush
。
有时问题只是&#34;调试软件&#34;。在这种情况下,您可以使用fflush
和setbuf
等函数来改变stdio流的缓冲行为,而不是重复调用setvbuf
。与添加大量fflush
调用相比,这更方便(更少甚至不需要代码更改 - 您可以使用标志控制set-buffering调用),因此可以将其视为问题使用(或过度使用)fflush
&#34;。
答案 1 :(得分:1)
嗯,@ torek的答案几乎是完美的,但有一点不太准确。
首先要考虑的是fflush仅在输出上定义 流。
根据man fflush,fflush也可用于输入流:
对于输出流,fflush()强制写入所有用户空间 通过流缓冲给定输出或更新流的数据 底层写功能。 :用于 输入流,fflush()丢弃从底层文件中提取但尚未被消耗的任何缓冲数据 应用程序。开放状态 流不受影响。 因此,当在输入中使用时,fflush只是丢弃它。
这是一个演示来说明它:
#include<stdio.h>
#define MAXLINE 1024
int main(void) {
char buf[MAXLINE];
printf("prompt: ");
while (fgets(buf, MAXLINE, stdin) != NULL)
fflush(stdin);
if (fputs(buf, stdout) == EOF)
printf("output err");
exit(0);
}
答案 2 :(得分:-1)
fflush()
清空与流相关的缓冲区。如果你是让用户在非常短的时间内(毫秒)输入一些数据并将一些内容写入文件中,写入和读取缓冲区可能还有一些“reststuff”。你调用fflush()
然后清空所有缓冲区并强制标准输出,以确保你得到的下一个输入是用户按下的内容。