【问题标题】:reading fprintf while the program is running在程序运行时读取 fprintf
【发布时间】:2012-03-24 03:32:46
【问题描述】:

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

【问题讨论】:

    标签: c string fopen printf formatted


    【解决方案1】:

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

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

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

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

    【讨论】:

    • 我实际上写得很频繁,这就是为什么我不想使用“每次打开和关闭”的方法,谢谢你告诉我到底发生了什么。我会尝试两种方法
    • 如果您只是定期刷新,那么您可能会丢失数据,因为程序在下一次刷新之前停止。如果您尝试捕捉信号,那么您可以更好地防止这种情况发生,这就是为什么两者都是理想的。如果您不是特别关心 IO 性能,则可以在每次写入后进行 fflush。根据内核和物理磁盘缓存的积极程度,每次写入后的 fflush 实际上可能对性能的影响非常小。
    【解决方案2】:

    每次你想写一条日志消息时,以追加模式打开文件,将你的文本打印到文件末尾,然后关闭它。

    【讨论】:

      【解决方案3】:

      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 好 2 好 3 好 4 好 5 好 6 好 ^C

      或者fflush(fh),当你想刷新写缓冲区时。

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

      【讨论】:

        【解决方案4】:

        我会接受 Corbin 的回答,但您问是否还有其他方法可以获取格式化输出。

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-06-15
          • 2011-06-30
          • 1970-01-01
          • 1970-01-01
          • 2012-02-16
          • 2013-01-25
          • 2022-07-23
          • 1970-01-01
          相关资源
          最近更新 更多