0

所以我正在编写一个假设在 C 中永远运行的程序(客户端服务器的东西),并且我正在写入日志。我正在使用fopen并且fprintf能够写入文件。我的问题是,由于该程序应该永远运行,所以我真的没有一点可以放fclose. 当我Ctrl+C停止进程和日志文件时,它什么也没显示?我想使用fprintf它,因为它允许我有格式化的字符串,有没有办法让我在仍然有格式化的字符串的同时记录我的输出?

4

4 回答 4

4

发生的事情是输出正在被缓冲,当程序被终止时,缓冲区永远不会刷新到磁盘。您可以定期刷新缓冲区 (fflush),也可以尝试捕获终止信号。具体来说,Control + C 发送 SIGINT 信号,因此您需要为此注册一个处理程序。

为了尽量减少潜在的缓冲损失,我可能会同时使用这两种策略。

如何捕捉 ctrl-c 事件?(C++)

编辑:正如亚当所说,您也可以在必要时打开和关闭文件,但根据您编写的频率,您可能希望保持文件打开,在这种情况下我的回答将适用。

于 2012-03-24T03:36:53.967 回答
1

每次您要编写日志消息时,以附加模式打开文件,将文本打印到文件末尾,然后将其关闭。

于 2012-03-24T03:35:48.127 回答
1

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) 刷新所有输出流。

于 2012-03-24T04:03:14.270 回答
0

我会接受 Corbin 的回答,但你问是否有另一种方法来获得格式化输出。

有:您可以将 sprintf() 用于 char 缓冲区,然后使用无缓冲open/write/closeI/O。

但是,不要那样做。继续使用 fopen() 和 co.,并捕获 SIGINT。

于 2012-03-24T04:49:43.450 回答