所以我正在编写一个程序,假设在C中永远运行(客户端服务器的东西),我正在写日志。我正在使用fopen
和fprintf
来写入文件。我的问题是,由于该程序被认为是永远运行的,因此我无需放置fclose
。当我 Ctrl + C 停止进程和日志文件时,它什么都没显示?我想使用fprintf
,因为它允许我使用格式化字符串,有没有办法让我在格式化字符串的同时记录输出?
答案 0 :(得分:4)
正在发生的事情是输出被缓冲,当程序被终止时,缓冲区永远不会被刷新到磁盘。您可以定期刷新缓冲区(fflush),也可以尝试捕获终止信号。具体来说,Control + C发送SIGINT信号,因此您需要为其注册处理程序。
为了尽可能减少潜在的缓冲损失,我可能会使用这两种策略。
编辑:正如亚当所说,你也可以在必要时打开和关闭文件,但根据你写作的频率,你可能希望保持文件打开,在这种情况下我的答案将适用。答案 1 :(得分:1)
每次要编写日志消息时,请以附加模式打开文件,将文本打印到文件末尾,然后将其关闭。
答案 2 :(得分:1)
setbuf(),setvbuf()或fflush(), - 和陷阱SIGINT
或与您的系统相关的内容。
即
#include <stdio.h>
#include <unistd.h> /* for sleep() in this example */
int main(void)
{
FILE *fh;
char *fn = "main.log";
int i;
if ((fh = fopen(fn, "w")) == NULL) {
fprintf(stderr,
"Unable to open file %s\n", fn);
return 1;
}
setbuf(fh, NULL); /* Turns buffering completely off */
for (i = 1; ; ++i) {
fprintf(fh, "%d ok ", i);
if (!(i%120))
fprintf(fh, "\n");
sleep(1);
}
fclose(fh);
return 0;
}
在其他控制台中:
$ tail -f main.log
产量: 1 ok 2 ok 3 ok 4 ok 5 ok 6 ok ^ C
或者当你想要刷新写缓冲区时fflush(fh)
。
<强> stdio.h产品:&gt; 强>
int setvbuf(FILE* stream, char* buf, int mode, size_t size);
控制流的缓冲。 mode是_IOFBF用于完全缓冲,_IOLBF用于行缓冲,_IONBF用于无缓冲。非null buf指定要使用的大小缓冲区;否则,分配缓冲区。出错时返回非零值。 呼叫必须在流上的任何其他操作之前。
void setbuf(FILE* stream, char* buf);
控制流的缓冲。对于null buf,关闭缓冲,否则等效于(void)setvbuf(stream,buf,_IOFBF,BUFSIZ)。
int fflush(FILE* stream);
刷新流媒体流并在成功时返回零或在出错时返回EOF。输入流的效果未定义。 fflush(NULL)刷新所有输出流。
答案 3 :(得分:0)
我会选择Corbin的答案,但你问是否有其他方法可以获得格式化输出。
有:您可以将sprintf()用于char缓冲区,然后使用无缓冲的open/write/close
I / O.
但是,不要这样做。继续使用fopen()和co。,并捕获SIGINT。