`fopen`, `fopen_s` 함수
fopen, fopen_s 함수 (fopen, fopen_s)
C에서 파일을 다루려면 먼저 그 파일을 열어야 해요. fopen은 파일 이름과 접근 모드를 주면 그 파일과 연결된 FILE* 스트림을 돌려주는, 파일 입출력의 가장 첫 관문이에요. 읽을지 쓸지, 덮어쓸지 이어 쓸지 같은 건 모두 mode 문자열로 정해요.
출처: cppreference
본문
함수 원형
<stdio.h>에 정의돼 있어요.
FILE* fopen( const char* filename, const char* mode ); // (1) (until C99)
FILE* fopen( const char* restrict filename, const char* restrict mode ); // (1) (since C99)
errno_t fopen_s( FILE* restrict* restrict streamptr,
const char* restrict filename,
const char* restrict mode ); // (2) (since C11)
설명 (Explanation)
filename이 가리키는 파일을 열고, 그 파일과 연결된 파일 스트림의 포인터를 돌려줘요.mode가 파일 접근 모드를 결정해요.- (1)과 같지만, 파일 스트림 포인터를
streamptr에 써 주고, 다음 오류들을 런타임에 감지해 현재 설치된 제약 처리 함수(constraint handler)를 호출해요.
streamptr이 널 포인터filename이 널 포인터mode가 널 포인터
다른 모든 경계 검사(bounds-checked) 함수와 마찬가지로, fopen_s는 구현이 __STDC_LIB_EXT1__을 정의하고, 사용자가 <stdio.h>를 포함하기 전에 __STDC_WANT_LIB_EXT1__을 정수 상수 1로 정의했을 때만 쓰는 게 보장돼요.
매개변수 (Parameters)
filename— 파일 스트림과 연결할 파일 이름mode— 파일 접근 모드를 결정하는 널 종료 문자열streamptr— 함수가 결과를 저장할 포인터를 가리키는 포인터(출력 매개변수)
파일 접근 플래그 (File access flags)
| 파일 접근 | mode 문자열 | 의미 | 설명 | 파일이 이미 있으면 | 파일이 없으면 |
|---|---|---|---|---|---|
| read | "r" |
읽기 | 읽기용으로 파일 열기 | 처음부터 읽기 | 열기 실패 |
| write | "w" |
쓰기 | 쓰기용으로 파일 만들기 | 내용 파괴 | 새로 만들기 |
| append | "a" |
이어 쓰기 | 파일에 이어 쓰기 | 끝에 쓰기 | 새로 만들기 |
| read extended | "r+" |
읽기/쓰기 | 읽기/쓰기용으로 파일 열기 | 처음부터 읽기 | 오류 |
| write extended | "w+" |
쓰기/읽기 | 읽기/쓰기용으로 파일 만들기 | 내용 파괴 | 새로 만들기 |
| append extended | "a+" |
이어 쓰기/읽기 | 읽기/쓰기용으로 파일 열기 | 끝에 쓰기 | 새로 만들기 |
몇 가지 플래그를 더 짚어 볼게요.
"b"플래그는 선택적으로 붙여 바이너리 모드로 열 수 있어요. POSIX에서는 아무 효과가 없지만, Windows에서는'\n'과'\x1A'의 특별 처리를 꺼 줘요.- append 접근 모드에서는 파일 위치 표시자가 어디 있든 데이터는 항상 파일 끝에 쓰여요.
- mode가 위에 나열된 문자열 중 하나가 아니면 동작이 정의되지 않아요. 일부 구현은 추가 모드(예: Windows)를 지원하기도 해요.
- 갱신(update) 모드(
'+')에서는 입력과 출력을 모두 할 수 있는데, 출력 뒤에 입력을 하려면 그 사이에fflush,fseek,fsetpos또는rewind를 호출해야 해요. 반대로 입력 뒤에 출력을 하려면fseek,fsetpos,rewind가 필요해요(입력 연산이 파일 끝을 만난 경우는 예외). "x"플래그는"w"나"w+"에 붙여서, 파일이 이미 존재하면 덮어쓰지 않고 실패하도록 만드는 기능이에요. (C11부터)fopen_s/freopen_s에서"w"나"a"로 만든 파일은 다른 사용자가 접근하지 못하게 권한이 설정돼요. 기본 fopen 권한을 쓰려면"w"나"a"로 시작하는 지정자 앞에"u"플래그를 붙여요. (C11부터)
반환값 (Return value)
- 성공하면 새 파일 스트림의 포인터를 돌려줘요.
filename이 대화형 장치가 아니라면 스트림은 완전 버퍼링(full buffering)돼요. 오류가 나면 널 포인터를 돌려주는데, POSIX는 이 경우errno를 설정하도록 요구해요(원문에 'POSIX requires'가 중복 표기되어 있어요). - 성공하면 0을 돌려주고
*streamptr에 새 파일 스트림 포인터를 써 줘요. 오류가 나면 0이 아닌 오류 코드를 돌려주고(단streamptr자체가 널이 아니라면)*streamptr에 널 포인터를 써 줘요.
주의할 점 (Notes)
filename의 형식은 구현이 정의하는데, 반드시 파일을 가리킬 필요는 없어요(예: 콘솔이나 파일시스템 API로 접근 가능한 다른 장치일 수도 있어요). 지원하는 플랫폼에서는 절대 경로나 상대 경로를 포함할 수 있어요.
예제 (Example)
"w+" 모드로 파일을 열어 문자열을 쓰고, 처음으로 되돌아간 뒤 한 글자씩 읽어 검증하는 예시예요.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
const char* fname = "/tmp/unique_name.txt"; // or tmpnam(NULL);
int is_ok = EXIT_FAILURE;
FILE* fp = fopen(fname, "w+");
if (!fp)
{
perror("File opening failed");
return is_ok;
}
fputs("Hello, world!\n", fp);
rewind(fp);
int c; // note: int, not char, required to handle EOF
while ((c = fgetc(fp)) != EOF) // standard C I/O file reading loop
putchar(c);
if (ferror(fp))
puts("I/O error when reading");
else if (feof(fp))
{
puts("End of file is reached successfully");
is_ok = EXIT_SUCCESS;
}
fclose(fp);
remove(fname);
return is_ok;
}
가능한 출력:
Hello, world!
End of file is reached successfully
같이 보기 (See also)
fclose— 파일 닫기fflush— 출력 스트림을 실제 파일과 동기화freopen/freopen_s— 기존 스트림을 다른 이름으로 다시 열기