在程序运行时读取fprintf

时间:2012-03-24 03:32:47

标签: c string fopen printf formatted

所以我正在编写一个程序,假设在C中永远运行(客户端服务器的东西),我正在写日志。我正在使用fopenfprintf来写入文件。我的问题是,由于该程序被认为是永远运行的,因此我无需放置fclose。当我 Ctrl + C 停止进程和日志文件时,它什么都没显示?我想使用fprintf,因为它允许我使用格式化字符串,有没有办法让我在格式化字符串的同时记录输出?

4 个答案:

答案 0 :(得分:4)

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

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

How can I catch a ctrl-c event? (C++)

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

答案 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。