C언어/stdio.h

[C언어] fopen 함수 (stdio.h)

아무일도없었다 2022. 8. 1. 01:12

사용범위

Windows, Unix 등 모든 OS에서 사용가능한 표준 API 함수

기능

C언어 표준 함수로 FILE 을 생성 또는 편집을 하기위해 사용한다.

헤더

#include <stdio.h>

※ fopen 함수 사용시 stdio.h 파일을 include 하지 않는다면 컴파일시 error 발생 ※


함수

FILE* fopen(const char *filename, const char *mode);

파라미터

  • const char* filename
    • 생성 또는 접근할 파일의 이름과 경로를 입력한다.
    • 파일의 이름만 입력시 상대경로로 접근한다.
  • const char *mode
    • 첫번째 파라미터인 filename 에 접근할 방식을 입력한다.

 


절대경로 ? 상대경로 ?
  • 절대경로
    • 절대경로란 파일의 위치를 가장 정확하게 나타내는 주소이며, 해당 파일의 위치를 최상단 폴더(directory)부터 나열한것을 말한다. (ex: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe)
    • 파일의 위치에 최상단 폴더부터 접근하기 때문에 권한만 있다면 어떤 위치에서도 해당 파일에 접근이 가능하다.
    • 모든 경로를 사용하기 때문에 파일 주소가 엄청나게 길어질 수도 있다. (fopen 사용시 buffer overflow 를 노리고 일부러 경로를 매우 복잡하게 하는 경우도 있다.)
  • 상대경로
    • 상대경로란 현재 작업중인 위치를 기준으로 파일의 나타내는 주소이며, 모든 기준은 나 자신이기 때문에 절대경로에 비해 상대적으로 간결하다.
    • 내 자신을 기준으로 움직이기 때문에 실행하는 위치가 변경될 경우 파일에 접근하지 못하는 문제가 발생할 수 있다.
  • Windows 경로
    • Windows OS는 경로에서 폴더(directory)간의 구분을 역슬래시(\) 문자로 구분하는데 C언어에서는 \ 문자는 탈출문자라고 불리며, 특수한 처리를 컴퓨터에게 알려주기 위해 사용한다. (ex: 개행문자('\n'), 텝문자('\t'), 역슬래시문자('\\') ... ) 
      따라서 fopen 함수를 Windows 에서 경로구분을 사용할때 폴더(directory) 구분을 역슬래시 두번(\\) 으로 한다.

mode ?
  • mode
    • 파일에 접근할 방식을 문자열로 입력하며 기본 "r" , "w" , "a"  3개와 "b" , "+" 2개의 선택적 조합으로 사용한다.
mode 의미 동작
r read - 읽기 (read) 권한으로 파일을 읽기 위해 오픈

- 반드시 파일이 존재해야함.
  (파일이 있는데 실패시 경로나 권한 확인)

- 파일이 있는 경우 맨 처음부터 데이터를 읽음
w write - 쓰기 (write) 권한으로 파일을 쓰기 위해 오픈

- 파일이 없는 경우 새로 생성

- 파일이 있는 경우 데이터를 모두 삭제하고 새로 생성
  (데이터 삭제 주의)
a append
(write)
- 쓰기 (write) 권한으로 파일을 오픈

- 파일이 없는 경우 새로 생성

- 파일이 있는 경우 데이터의 맨 마지막부터 내용을 추가
r+ read & write - 읽기/쓰기 (read & write) 권한으로 파일을 읽기 위해 오픈

- 반드시 파일이 존재해야함.
  (파일이 있는데 실패시 경로나 권한 확인)

- 파일이 있는 경우 맨 처음부터 데이터를 읽음
w+ read & write - 읽기/쓰기 (read & write) 권한으로 파일을 쓰기 위해 오픈

- 파일이 없는 경우 새로 생성

- 파일이 있는 경우 데이터를 모두 삭제하고 새로 생성
  (데이터 삭제 주의)
a+  append
(read & write)
- 읽기/쓰기 (read &write) 권한으로 파일을 오픈

- 파일이 없는 경우 새로 생성

- 파일이 있는 경우 데이터의 맨 마지막부터 내용을 추가
rb read
(binary file)
- 읽기 (read) 권한으로 이진파일을 읽기 위해 오픈 (binary file)

- 반드시 파일이 존재해야함.
  (파일이 있는데 실패시 경로나 권한 확인)

- 파일이 있는 경우 맨 처음부터 데이터를 읽음
wb write
(binary file)
- 쓰기 (write) 권한으로 이진파일을 쓰기 위해 오픈 (binary file)

- 파일이 없는 경우 새로 생성

- 파일이 있는 경우 데이터를 모두 삭제하고 새로 생성
  (데이터 삭제 주의)
ab append
(write & binary file)
- 쓰기 (write) 권한으로 이진파일을 오픈 (binary file)

- 파일이 없는 경우 새로 생성

- 파일이 있는 경우 데이터의 맨 마지막부터 내용을 추가
r+b 또는 rb+ read & write
(binary file)
읽기/쓰기 (read & write) 권한으로 이진파일을 읽기 위해 오픈
  (binary file)

반드시 파일이 존재해야함.
  (파일이 있는데 실패시 경로나 권한 확인)

- 파일이 있는 경우 맨 처음부터 데이터를 읽음
w+b 또는 wb+ read & write
(binary file)
읽기/쓰기 (read & write) 권한으로 이진파일을 쓰기 위해 오픈
  (binary file)

파일이 없는 경우 새로 생성

- 파일이 있는 경우 데이터를 모두 삭제하고 새로 생성
  (데이터 삭제 주의)
a+b 또는 ab+ append
(read & write & binary file)
-읽기/쓰기 (read &write) 권한으로 이진파일을 오픈
  (binary file)

-파일이 없는 경우 새로 생성

- 파일이 있는 경우 데이터의 맨 마지막부터 내용을 추가

 

 


반환값

성공시   File Stream 포인터를 반환한다. 
실패시   NULL을 반환한다.

 

File Stream ?
  • File Stream
    • 특정 파일과 매칭되어 사용자와 파일간의 통로 역할을 한다.
    • 사용자(User)가 직접 하드웨어에 접근해서 처리를 하려면 굉장히 복잡하고 위험하기 때문에 OS에서 관리되는 Stream을 통해 간접적으로 제어를 하는 장치이다.
    • 흔히(?) 사용하던 콘솔 입출력 또한 하나의 stream 이다.

 


주의사항

fopen 함수를 통해 생성된 file stream 은 OS에서 한정적인 리소스(자원) 이다. (ex: CPU, Memory , ...)

개발자가 fclose 함수를 통해 명시적으로 file stream을 닫아주지 않는다면 해당 프로세스는 계속해서 해당 자원을 점유하게 될것이다.

만약 fclose 함수로 file stream을 닫지 않고 계속해서 fopen 함수를 통해 file stream을 생성한다면, 나중에는 OS에서 사용할 Stream 자원이 부족해지는 대형 사고가 발생하게 된다. (이 현상을 파일 디스크립터 누수 라고 한다.)

따라서 사용이 끝난 file stream은 fclose 함수를 통해서 닫아주는 습관을 가지는게 좋다.

 


 

<소스 코드>

#include <stdio.h>

#define MAX_BUF_SIZE 128

int main() {
    FILE* fp;
    int ret;
    char buffer[MAX_BUF_SIZE] = "Hello fopen";

    fp = fopen("test.txt", "w");
    if (fp != NULL) {
        ret = fputs(buffer, fp);
        if (ret != EOF) {
            printf("ret = %d\n", ret);
        } else {
            // fputs 함수 실패 !
        }
        fclose(fp);
    } else {
        printf("fopen 함수 실패!\n);
    }
    return 0;
}

 

※ 실행 결과

ret = 0

 

< test.txt >

Hello fopen
반응형

'C언어 > stdio.h' 카테고리의 다른 글

[C언어] fread 함수 (stdio.h)  (0) 2022.08.03
[C언어] fclose 함수 (stdio.h)  (0) 2022.08.02
[C언어] fputs 함수 (stdio.h)  (0) 2022.07.28
[C언어] fgets 함수 (stdio.h)  (0) 2022.07.26
[C언어] scanf 함수 (stdio.h)  (0) 2022.07.24