所以我正在编写一个假设在 C 中永远运行的程序(客户端服务器的东西),并且我正在写入日志。我正在使用fopen
并且fprintf
能够写入文件。我的问题是,由于该程序应该永远运行,所以我真的没有一点可以放fclose
. 当我Ctrl+C停止进程和日志文件时,它什么也没显示?我想使用fprintf
它,因为它允许我有格式化的字符串,有没有办法让我在仍然有格式化的字符串的同时记录我的输出?
4 回答
发生的事情是输出正在被缓冲,当程序被终止时,缓冲区永远不会刷新到磁盘。您可以定期刷新缓冲区 (fflush),也可以尝试捕获终止信号。具体来说,Control + C 发送 SIGINT 信号,因此您需要为此注册一个处理程序。
为了尽量减少潜在的缓冲损失,我可能会同时使用这两种策略。
编辑:正如亚当所说,您也可以在必要时打开和关闭文件,但根据您编写的频率,您可能希望保持文件打开,在这种情况下我的回答将适用。
每次您要编写日志消息时,以附加模式打开文件,将文本打印到文件末尾,然后将其关闭。
setbuf()、setvbuf() 或 fflush(),- 以及陷阱SIGINT
或任何与您的系统相关的合适的东西。
IE
#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)
当你想刷新写缓冲区时。
标准输入输出.h:>
int setvbuf(FILE* stream, char* buf, int mode, size_t size);
控制流流的缓冲。模式是 _IOFBF 用于完全缓冲,_IOLBF 用于行缓冲,_IONBF 用于无缓冲。非空 buf 指定要使用的大小大小的缓冲区;否则,分配一个缓冲区。出错时返回非零值。调用必须在流上的任何其他操作之前。
void setbuf(FILE* stream, char* buf);
控制流流的缓冲。对于 null buf,关闭缓冲,否则等价于 (void)setvbuf(stream, buf, _IOFBF, BUFSIZ)。
int fflush(FILE* stream);
刷新流并在成功时返回零或在错误时返回 EOF。输入流的效果未定义。fflush(NULL) 刷新所有输出流。
我会接受 Corbin 的回答,但你问是否有另一种方法来获得格式化输出。
有:您可以将 sprintf() 用于 char 缓冲区,然后使用无缓冲open/write/close
I/O。
但是,不要那样做。继续使用 fopen() 和 co.,并捕获 SIGINT。