这个stdout重定向如何工作?

vin*_*dyz 5 c c++ programming-languages

下面的代码将stdout重定向到文件fname,然后重定向回原始标准输出.这对我来说可以.但我无法理解它是如何运作的.如果有人能帮助我理解我将会相信它.

    printf("\n This is console");
    fflush(stdout);
    fgetpos(stdout, &pos);
    fd = dup(fileno(stdout));
    freopen(fname, "a+", stdout);   

    printf("inside file op");  

    fflush(stdout);
    dup2(fd,fileno(stdout));
    close(fd);
    clearerr(stdout);
    fsetpos(stdout, &pos);
    printf("\nBack to Console");
Run Code Online (Sandbox Code Playgroud)

ick*_*fay 14

让我们一行一行地完成它.第一行打印的内容为stdout:

printf("\n This is console");
Run Code Online (Sandbox Code Playgroud)

然后它会刷新,stdout因此缓冲区中的所有剩余数据都会被发送到stdout文件数据并且不会与文件数据混淆:

fflush(stdout);
Run Code Online (Sandbox Code Playgroud)

现在我们存储自己的当前位置,stdout因为否则如果stdout已经定向到文件,我们可能(?)覆盖它的早期部分.

fgetpos(stdout, &pos);
Run Code Online (Sandbox Code Playgroud)

现在我们克隆当前的文件描述符stdout.由于我们即将改变stdout点数,我们需要保留原始副本:

fd = dup(fileno(stdout));
Run Code Online (Sandbox Code Playgroud)

现在我们保留了所有内容,我们可以重新打开stdout文件:

freopen(fname, "a+", stdout);
Run Code Online (Sandbox Code Playgroud)

此时,stdout已被重定向到该文件.我们现在可以打印到它:

printf("inside file op");  
Run Code Online (Sandbox Code Playgroud)

现在我们已经完成了对文件的打印.我们需要刷新stdout(现在是文件),这样它就不会与普通stdout数据混淆:

fflush(stdout);
Run Code Online (Sandbox Code Playgroud)

之后,我们stdout在当前stdout描述符上克隆原始文件描述符.

dup2(fd,fileno(stdout));
Run Code Online (Sandbox Code Playgroud)

克隆的一个现在可以关闭:

close(fd);
Run Code Online (Sandbox Code Playgroud)

我不太清楚为什么会这样,但这会清除写入文件时发生的任何错误:

clearerr(stdout);
Run Code Online (Sandbox Code Playgroud)

现在我们恢复我们的位置stdout.同样,据我所知,这只有在最初重定向到文件时才有用:

fsetpos(stdout, &pos);
Run Code Online (Sandbox Code Playgroud)

现在我们又回到了原版stdout,所以我们可以再次打印:

printf("\nBack to Console");
Run Code Online (Sandbox Code Playgroud)