如何在C中将重定向输出写入循环内部的文件?

如何在C中将重定向输出写入循环内部的文件?,c,file,unix,redirect,C,File,Unix,Redirect,我正在unix上编写一个C程序,该程序应将其输出重定向到文件,并在无限循环中每秒向其写入一些文本: #include <fcntl.h> #include <stdio.h> #include <unistd.h> int main(void) { int outDes = open("./output.txt", O_APPEND | O_WRONLY); dup2(outDes, 1); while(1) { pr

我正在unix上编写一个C程序,该程序应将其输出重定向到文件,并在无限循环中每秒向其写入一些文本:

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>

int main(void) {
    int outDes = open("./output.txt", O_APPEND | O_WRONLY);
    dup2(outDes, 1);
    while(1) {
        printf("output text\n");
        sleep(1);
    }
}
将输出重定向到文件之前。然后程序将这些行实时写入文件,这很好,但也会在其中写入第一行(非重定向)。我不想在我的输出文件中出现这第一行,我不明白在输出还没有重定向的情况下,如何将其写入文件(可能重定向自上次运行以来一直存在?),以及如何导致这些行突然被实时写入

有人能解释一下它是怎么工作的吗

  • 您没有检查open()和dup2()的返回值。如果open()或dup2()失败,它将不会在output.txt中写入任何内容

    if (outDes < -1) {
        perror("open");
        return 1;
    }
    if (dup2(outDes, 1) == -1) {
        perror("dup2");
        return 1;
    }
    
    if(outDes<-1){
    佩罗(“公开”);
    返回1;
    }
    如果(dup2(输出端,1)=-1){
    perror(“dup2”);
    返回1;
    }
    
  • stdio流被缓冲,写操作在对真实文件描述执行之前发生在内存中

    尝试在
    printf()之后添加
    fflush(stdout)

  • 您没有检查open()和dup2()的返回值。如果open()或dup2()失败,它将不会在output.txt中写入任何内容

    if (outDes < -1) {
        perror("open");
        return 1;
    }
    if (dup2(outDes, 1) == -1) {
        perror("dup2");
        return 1;
    }
    
    if(outDes<-1){
    佩罗(“公开”);
    返回1;
    }
    如果(dup2(输出端,1)=-1){
    perror(“dup2”);
    返回1;
    }
    
  • stdio流被缓冲,写操作在对真实文件描述执行之前发生在内存中

    尝试在
    printf()之后添加
    fflush(stdout)


  • 在许多Unix C库中,您遇到了一个文档记录不完整的DWIMmy特性。第一次写入
    stdout
    stderr
    时,库会探测底层文件描述符(使用)。如果是(伪)终端,库会将文件置于“行缓冲”模式,这意味着它将缓冲输入,直到写入换行符,然后将其全部刷新到操作系统。但是,如果文件描述符不是终端,它会将文件置于“完全缓冲”模式,在刷新输出字节之前,它会缓冲类似于
    BUFSIZ
    的字节,而不注意换行

    这通常是您想要的行为,但是如果您不想要它(在本例中),您可以使用更改它。这个函数(虽然不是我上面描述的行为)是ISO标准C。下面是如何在您的案例中使用它

    #include <stdio.h>
    #include <unistd.h>
    
    int
    main(void)
    {
        if (freopen("output.txt", "a", stdout)) {
            perror("freopen");
            return 1;
        }
        if (setvbuf(stdout, 0, _IOLBF, 0)) {
            perror("setvbuf");
            return 1;
        }
    
        for (;;) {
            puts("output text");
            sleep(1);
        }
        /* not reached */
    }
    
    #包括
    #包括
    int
    主(空)
    {
    if(freopen(“output.txt”,“a”,stdout)){
    佩罗尔(“弗罗普”);
    返回1;
    }
    if(setvbuf(标准输出,0,_IOLBF,0)){
    perror(“setvbuf”);
    返回1;
    }
    对于(;;){
    puts(“输出文本”);
    睡眠(1);
    }
    /*未达到*/
    }
    
    在许多Unix C库中,您遇到了一个文档不完整的DWIMmy特性。第一次写入
    stdout
    stderr
    时,库会探测底层文件描述符(使用)。如果是(伪)终端,库会将文件置于“行缓冲”模式,这意味着它将缓冲输入,直到写入换行符,然后将其全部刷新到操作系统。但是,如果文件描述符不是终端,它会将文件置于“完全缓冲”模式,在刷新输出字节之前,它会缓冲类似于
    BUFSIZ
    的字节,而不注意换行

    这通常是您想要的行为,但是如果您不想要它(在本例中),您可以使用更改它。这个函数(虽然不是我上面描述的行为)是ISO标准C。下面是如何在您的案例中使用它

    #include <stdio.h>
    #include <unistd.h>
    
    int
    main(void)
    {
        if (freopen("output.txt", "a", stdout)) {
            perror("freopen");
            return 1;
        }
        if (setvbuf(stdout, 0, _IOLBF, 0)) {
            perror("setvbuf");
            return 1;
        }
    
        for (;;) {
            puts("output text");
            sleep(1);
        }
        /* not reached */
    }
    
    #包括
    #包括
    int
    主(空)
    {
    if(freopen(“output.txt”,“a”,stdout)){
    佩罗尔(“弗罗普”);
    返回1;
    }
    if(setvbuf(标准输出,0,_IOLBF,0)){
    perror(“setvbuf”);
    返回1;
    }
    对于(;;){
    puts(“输出文本”);
    睡眠(1);
    }
    /*未达到*/
    }
    
    我也是这么想的,但是OP是printint a
    “\n”
    ,所以它应该刷新。@Chris:一些Unix C库决定
    stdout
    在第一次写入时是否是一个终端(因此是否对其进行行缓冲)。通过在第一次写入之前交换文件描述符1,OP向库显示它不是一个终端。@Zach-这非常聪明。我也是这么想的,但是OP打印在一个
    “\n”
    中,所以它应该刷新。@Chris:一些Unix C库决定
    stdout
    是否是终端第一次写入时(以及是否对其进行行缓冲)。通过在第一次写入之前交换文件描述符1,OP向库显示它不是终端。@Zach-这非常聪明。