`freopen`, `freopen_s` 함수

freopen, freopen_s 함수 (freopen, freopen_s)

이미 열려 있는 스트림을 다른 파일에 연결하고 싶을 때가 있어요. 예를 들어 stdout을 콘솔 대신 파일로 보내고 싶다든지요. 이때 스트림을 닫았다 다시 여는 대신 쓸 수 있는 함수가 freopen이에요. 기존 스트림의 버퍼와 메모리를 그대로 재사용하면서 목적지만 바꿔 주는 셈이죠.

출처: cppreference

본문

함수 원형

<stdio.h>에 정의돼 있어요.

FILE* freopen( const char* filename, const char* mode,
               FILE* stream );                                  // (1) (until C99)
FILE* freopen( const char* restrict filename, const char* restrict mode,
               FILE* restrict stream );                         // (1) (since C99)
errno_t freopen_s( FILE* restrict* restrict newstreamptr,
                   const char* restrict filename, const char* restrict mode,
                   FILE* restrict stream );                     // (2) (since C11)

설명 (Explanation)

  1. 먼저 stream과 연결된 파일을 닫으려 시도해요(이때 오류는 무시돼요). 그 다음 filename이 널이 아니라면, filename이 가리키는 파일을 fopen처럼 mode로 열어서 stream이 가리키는 파일 스트림에 연결해요. filename이 널 포인터면, stream에 이미 연결된 파일을 다시 열려고 시도해요(이 경우 어떤 mode 변경이 허용될지는 구현이 정의해요).
  2. (1)과 같지만, modefopen_s처럼 다루고, 파일 스트림 포인터를 newstreamptr에 써 주며, 다음 오류들을 런타임에 감지해 현재 설치된 제약 처리 함수(constraint handler)를 호출해요.
  • newstreamptr이 널 포인터
  • stream이 널 포인터
  • mode가 널 포인터

다른 경계 검사 함수와 마찬가지로, freopen_s는 구현이 __STDC_LIB_EXT1__을 정의하고, 사용자가 <stdio.h>를 포함하기 전에 __STDC_WANT_LIB_EXT1__을 정수 상수 1로 정의했을 때만 쓰는 게 보장돼요.

매개변수 (Parameters)

  • filename — 파일 스트림과 연결할 파일 이름
  • mode — 새 파일 접근 모드를 결정하는 널 종료 문자열
  • stream — 수정할 파일 스트림
  • newstreamptr — 함수가 결과를 저장할 포인터를 가리키는 포인터(출력 매개변수)

파일 접근 플래그 (File access flags)

mode 문자열의 의미는 fopen과 동일해요.

파일 접근 mode 문자열 의미 설명 파일이 이미 있으면 파일이 없으면
read "r" 읽기 읽기용으로 파일 열기 처음부터 읽기 열기 실패
write "w" 쓰기 쓰기용으로 파일 만들기 내용 파괴 새로 만들기
append "a" 이어 쓰기 파일에 이어 쓰기 끝에 쓰기 새로 만들기
read extended "r+" 읽기/쓰기 읽기/쓰기용으로 파일 열기 처음부터 읽기 오류
write extended "w+" 쓰기/읽기 읽기/쓰기용으로 파일 만들기 내용 파괴 새로 만들기
append extended "a+" 이어 쓰기/읽기 읽기/쓰기용으로 파일 열기 끝에 쓰기 새로 만들기

플래그 규칙도 fopen과 같아서, "b"(바이너리), "x"(이미 존재하면 실패, C11), "u"(기본 권한, C11) 등을 쓸 수 있어요. 갱신 모드('+')에서는 입력·출력 사이에 위치 이동 함수를 호출해 줘야 한다는 규칙도 동일해요.

반환값 (Return value)

  1. 성공하면 stream의 값의 복사본을, 실패하면 널 포인터를 돌려줘요.
  2. 성공하면 0을 돌려주고 *newstreamptrstream 값의 복사본을 써 줘요. 오류가 나면 0이 아닌 값을 돌려주고(단 newstreamptr 자체가 널이 아니라면) *newstreamptr에 널 포인터를 써 줘요.

주의할 점 (Notes)

freopen은 스트림이 I/O 연산이나 fwide에 의해 설정된 후에 좁은/넓은 지향(orientation)을 바꿀 수 있는 유일한 방법이에요.

Microsoft CRT 버전의 freopenfilename이 널 포인터일 때 mode 변경을 지원하지 않고 이를 오류로 처리해요(문서 참고). 가능한 우회 방법은 비표준 함수인 _setmode()예요.

예제 (Example)

stdout을 파일 redir.txt로 리다이렉트하는 예시예요. 리다이렉트를 건 뒤의 puts는 콘솔이 아니라 파일에 쓰여요.

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    puts("stdout is printed to console");

    if (freopen("redir.txt", "w", stdout) == NULL)
    {
       perror("freopen() failed");
       return EXIT_FAILURE;
    }

    puts("stdout is redirected to a file"); // this is written to redir.txt
    fclose(stdout);
    return EXIT_SUCCESS;
}

출력:

stdout is printed to console

같이 보기 (See also)

  • fopen/fopen_s — 파일 열기
  • fclose — 파일 닫기