`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)
- 먼저
stream과 연결된 파일을 닫으려 시도해요(이때 오류는 무시돼요). 그 다음filename이 널이 아니라면,filename이 가리키는 파일을fopen처럼mode로 열어서stream이 가리키는 파일 스트림에 연결해요.filename이 널 포인터면,stream에 이미 연결된 파일을 다시 열려고 시도해요(이 경우 어떤 mode 변경이 허용될지는 구현이 정의해요). - (1)과 같지만,
mode를fopen_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)
- 성공하면
stream의 값의 복사본을, 실패하면 널 포인터를 돌려줘요. - 성공하면 0을 돌려주고
*newstreamptr에stream값의 복사본을 써 줘요. 오류가 나면 0이 아닌 값을 돌려주고(단newstreamptr자체가 널이 아니라면)*newstreamptr에 널 포인터를 써 줘요.
주의할 점 (Notes)
freopen은 스트림이 I/O 연산이나 fwide에 의해 설정된 후에 좁은/넓은 지향(orientation)을 바꿀 수 있는 유일한 방법이에요.
Microsoft CRT 버전의 freopen은 filename이 널 포인터일 때 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— 파일 닫기