programing

프리오픈 후 출력을 다시 화면으로 리디렉션하는 방법("out.txt", "a", stdout)

muds 2023. 10. 13. 22:37
반응형

프리오픈 후 출력을 다시 화면으로 리디렉션하는 방법("out.txt", "a", stdout)

#include <stdio.h>

int main() {
    printf("This goes to screen\n");
    freopen("out.txt", "a", stdout);
    printf("This goes to out.txt");
    freopen("/dev/stdout", "a", stdout);
    printf("This should go to screen too, but doesn't\n");

    return 0;
}

freopen에 전화해서 stdout을 밖으로 재연결합니다.txt 그런 다음 파일에 무언가를 인쇄하면 화면으로 다시 리디렉션하려고 하는데 freopen("/dev/stdout", "a", stdout); 작동하지 않습니다.ANSIC 또는 POSIX 시스템 호출을 사용하여 수행할 수 있는 방법이 있습니까?

할 시스템 POSIX 호환 GNU/리눅스 ( POSIX ) 에서는를 할 수 .freopen ("/dev/tty", "a", stdout) 이게 당신이 하려고 했던 일인가요?

안타깝게도 좋은 방법은 없는 것 같습니다.

http://c-faq.com/stdio/undofreopen.html

이런 상황에서는 프리오픈을 사용하지 않는 것이 가장 좋습니다.

일반적으로 말하면 안 됩니다.파일을 닫으셨군요 파이프 같은 것일 수도 있고요다시 열 수 없습니다.다를 .stdout지정한 을 다시 복사합니다 value합니다 fopen음.예:

FILE *o = stdout;
stdout=fopen("/tmp/crap.txt","a");
printf("Oh no!\n");
fclose(stdout);
stdout = o;

Mike Weller는 stdout이 항상 쓰기 가능한 것은 아닐 수도 있다는 의견을 아래에 제시했습니다.이 경우 다음과 같은 것이 도움이 될 수 있습니다.

int o = dup(fileno(stdout));
freopen("/tmp/crap.txt","a",stdout);
printf("Oh no!\n");
dup2(o,fileno(stdout));
close(o);

다른 편집: 코멘트가 다른 곳에서 제안하는 것처럼 하위 프로세스의 출력을 리디렉션하는 데 사용하는 경우 포크 후에 리디렉션할 수 있습니다.

사용하다fdopen()그리고.dup()만 아니라.freopen().

int old_stdout = dup(1);  // Preserve original file descriptor for stdout.

FILE *fp1 = freopen("out.txt", "w", stdout);  // Open new stdout

...write to stdout...   // Use new stdout

FILE *fp2 = fdopen(old_stdout, "w");   // Open old stdout as a stream

...Now, how to get stdout to refer to fp2?
...Under glibc, I believe you can use:

fclose(stdout);    // Equivalent to fclose(fp1);
stdout = fp2;      // Assign fp2 to stdout
// *stdout = *fp2;   // Works on Solaris and MacOS X, might work elsewhere.

close(old_stdout);   // Close the file descriptor so pipes work sanely

당신이 다른 곳에서 과제를 신뢰성 있게 수행할 수 있을지 잘 모르겠습니다.

실제로 작동하는 의심스러운 코드

아래 코드는 Solaris 10과 MacOS X 10.6.2에서 작동했지만 신뢰할 수 있을지 확신할 수 없습니다.구조 할당은 Linux glibc에서 작동할 수도 있고 작동하지 않을 수도 있습니다.

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

int main(void)
{
    printf("This goes to screen\n");
    int old_stdout = dup(1);  // Consider dup(STDOUT_FILENO) or dup(fileno(stdout))
    FILE *fp1 = freopen("out.txt", "a", stdout);
    printf("This goes to out.txt\n");
    fclose(stdout);
    FILE *fp2 = fdopen(old_stdout, "w");
    *stdout = *fp2;                       // Unreliable!
    printf("This should go to screen too, but doesn't\n");

    return 0;
}

당신이 경고를 받지 않았다고 말할 수는 없겠지요. 이건 불장난이에요!

/dev/fd다템에서 암시된 할 수 .dup()와 함께sprintf(buffer, "/dev/fd/%d", old_stdout)그 다음에 사용합니다.freopen()그 이름으로 이것 코드에서 할 수 .이것은 이 코드에 사용된 할당보다 훨씬 더 신뢰할 수 있습니다.

더 나은 솔루션은 코드가 어디에서나 'fprintf(fprintf, ...)'를 사용하게 하거나, 사용자 자신의 기본 파일 포인터를 설정할 수 있는 커버 기능을 사용합니다.

mprintf.c

#include "mprintf.h"
#include <stdarg.h>

static FILE *default_fp = 0;

void set_default_stream(FILE *fp)
{
    default_fp = fp;
}

int mprintf(const char *fmt, ...)
{
    va_list args;
    va_start(args, fmt);

    if (default_fp == 0)
        default_fp = stdout;

    int rv = vfprintf(default_fp, fmt, args);

    va_end(args);
    return(rv);
 }

mprintf.h

#ifndef MPRINTF_H_INCLUDED
#define MPRINTF_H_INCLUDED

#include <stdio.h>

extern void set_default_stream(FILE *fp);
extern int  mprintf(const char *fmt, ...);

#endif

필요에 따라 mvprintf() 및 기타 기능을 생성할 수 있습니다.

mprintf()의 예시적인 사용

그러면 원래 코드 대신 다음을 사용할 수 있습니다.

#include "mprintf.h"

int main()
{
    mprintf("This goes to screen\n");
    FILE *fp1 = fopen("out.txt", "w");
    set_default_stream(fp1);
    mprintf("This goes to out.txt\n");
    fclose(fp1);
    set_default_stream(stdout);
    mprintf("This should go to screen too, but doesn't\n");

    return 0;
}

(경고: 테스트되지 않은 코드 - 신뢰 수준이 너무 높습니다.또한, 모든 코드는 C99 컴파일러를 사용한다고 가정하여 작성되었는데, 주된 이유는 함수의 시작이 아니라 변수가 처음 필요할 때 선언하기 때문입니다.)


주의:

원래 프로그램이 다음과 같이 호출되는 경우 주의하십시오../original_program > file아니면./original_program | grep something(방향 전환된 출력으로) 또는 A에서 실행됩니다.cron작업, 그 다음/dev/tty원래 표준 출력이 터미널이 아니었기 때문에 표준 출력을 다시 여는 방법으로는 일반적으로 적절치 않습니다.

또한 자식 프로그램을 포킹하고 실행하기 전에 표준 출력의 리디렉션을 사용하고 원래 표준 출력을 상위 프로그램에 복원하면 작업 순서가 잘못됩니다.부모의 I/O를 수정하지 않고 포크를 사용한 다음 자식의 I/O를 조정해야 합니다.

Windows에서 "CONOUT$"를 열 수 있습니다.

freopen("test.txt", "w", stdout);
printf("this goes to test.txt");
freopen("CONOUT$", "w", stdout);
printf("this goes to the console\n");

stdout을 처음부터 재연결하는 경우에는 이 작업이 수행되지 않을 수 있습니다.

예상 결과 파일과 비교하기 위해 stdout 스트림을 저장하려는 테스트 벤치에는 다음 코드(SwapIOB)가 사용됩니다.

배경:파일 스트림은 20개의 _IOB 항목 배열에 저장되는 _IOB 구조를 사용하여 관리됩니다.여기에는 stdout 스트림이 포함됩니다.IOB는 배열로 저장됩니다.파일이 생성되면 해당 배열의 요소에 응용 프로그램 코드가 적용됩니다.그런 다음 애플리케이션 코드는 I/O 호출을 처리하기 위해 해당 ptr을 OS로 전달합니다.따라서 OS 자체가 애플리케이션의 IOB에 대한 자체 포인터를 포함하거나 의존하지 않습니다.

요구사항:테스트벤치를 실행할 때는 응용프로그램이 발행한 stdout 메시지를 파일로 리디렉션해야 합니다.그러나 테스트 대상 모듈이 완료된 후에는 stdout 메시지를 콘솔로 재연결해야 합니다.

이 루틴은 테스트되었으며 현재 Windows XP/Pro 시스템에서 사용되고 있습니다.

void SwapIOB(FILE *A, FILE *B) {

    FILE temp;

    // make a copy of IOB A (usually this is "stdout")
    memcpy(&temp, A, sizeof(struct _iobuf));

    // copy IOB B to A's location, now any output
    // sent to A is redirected thru B's IOB.
    memcpy(A, B, sizeof(struct _iobuf));

    // copy A into B, the swap is complete
    memcpy(B, &temp, sizeof(struct _iobuf));

}  // end SwapIOB;

응용 프로그램 코드는 다음과 유사하게 SwapIOB()를 사용합니다.

FILE *fp;

fp = fopen("X", "w");

SwapIOB(stdout, fp);

printf("text to file X");

SwapIOB(stdout, fp);

fclose(fp);

printf("text to console works, again!");

언급URL : https://stackoverflow.com/questions/1908687/how-to-redirect-the-output-back-to-the-screen-after-freopenout-txt-a-stdo

반응형