목차
- 파일을 여는 fopen과 파일을 닫는 fclose
- 스트림과 파일 포인터
- 텍스트 파일과 바이너리 파일
1. 파일을 여는 fopen과 파일을 닫는 fclose
앞서 우리는 키보드를 통해 데이터를 입출력받았습니다.
그런데 프로그램이 끝나면 내부의 데이터가 다 날아가버리네요..
그런데 대부분 일회성 데이터를 다루는 것은 드물겁니다. 학점이라던가, 이름이라던가..
이런게 바로 날아가면 무슨 상관인가요?
이러한 데이터의 대부분은 하드디스크에 저장하고 다시 불러들입니다.
이렇게 저장하고 불러들이기 위해 파일 입출력에 대해 알아봅시다.
일단 먼저 파일을 찾아서 열어야겠죠, 이때 사용하는 함수가 fopen입니다.
그리고 마지막에는 파일을 닫아야 합니다. 파일을 안 닫으면 큰일나요. 이때는 함수 fclose를 사용합니다.
다음과 같은 예제를 봅시다.
#include <stdio.h>
int main(void)
{
// FILE 포인터 선언: 파일 입출력에 사용되는 구조체의 주소를 저장하기 위한 포인터
FILE* fp;
// 파일 열기:
// 첫 번째 인자는 열 파일의 경로(E:\project\ConsoleApplication1, \\을 두 번 쓰면 \으로 처리됨)
// 두 번째 인자는 파일 열기 모드("r"은 읽기 모드)
fp = fopen("E:\\project\\ConsoleApplication1\\test.txt", "r");
// 파일 열기에 실패한 경우, fp는 NULL이 됩니다.
if (fp == NULL)
{
// 에러 메시지를 출력 후, 프로그램을 비정상 종료 (1을 반환)
printf("파일을 열 수 없습니다.\n");
return 1;
}
// 파일이 성공적으로 열렸으면 메시지 출력
printf("파일이 열렸습니다.\n");
// 파일 사용이 끝난 후, 자원 해제를 위해 파일을 닫습니다.
fclose(fp);
return 0;
}
출력은 다음과 같습니다.
자신의 실행 파일 위치랑 동일한 곳에 txt 파일을 위치시켜야 합니다.
파일이 열렸습니다.
..
이상한게 너무 많은데요?
에.. 거의 웬만한 부분들은 주석에 들어있으니 상세히 읽어주세요.
파일이 잘 열리는지 잘 열리지 않는지를 확인하기 위해 if부터 시작하는 예외처리 부분이 꼭 필요합니다.
그리고 파일은 포인터로 열어야 합니다.
fopen은 fopen("첫 번째 인자", "두 번째 인자")로 구성되어 있는데, 첫 번째 인자는 파일의 경로.
즉 이걸 의미합니다.

그리고 두 번째 인자는 파일을 어떤 "모드" 로 열 것인가를 의미합니다.
지금같은 경우, r(read)읽기 모드로 열었지만..
필요하면 w(write)쓰기 모드 등으로도 열 수 있습니다.
모드 | 설명 |
"r" | 읽기 모드로 파일 열기 |
"w" | 쓰기 모드로 파일 생성 (이미 존재하면 기존의 내용은 초기화됨) |
"a" | 추가 모드로 파일 열기(기존 데이터의 끝에 추가) 파일이 없으면 w모드 처럼 파일을 생성합니다. |
"r+" | 읽기 모드로 파일 열기, 쓰기 모드로 전환 가능 |
"w+" | 쓰기 모드로 파일 생성, 읽기 모드로 전환 가능 (이미 존재하면 기존의 내용은 초기화됨) |
"a+" | 추가 모드로 파일 열기, 읽기 모드로 전환 가능 파일이 없으면 w모드 처럼 파일을 생성합니다. |
"t" | 텍스트 파일 모드로 파일 열기, rt, wt, at 등으로 사용됨 |
"b" | 이진 파일 모드로 파일 열기, rb, wb, ab 등으로 사용됨 |
이것들은 조합할 수 있습니다.
뭐, w+b도 가능하고..
t는 기본값이라 생략 가능합니다.
2. 스트림과 파일 포인터
스트림 파일은 프로그램과 입출력 장치 사이의 다리 역할을 하는 파일입니다.
즉, 스트림은 데이터를 임시저장하는 버퍼 역할을 합니다.
스트림 파일은 문자 배열 형태의 버퍼를 가지고 있습니다.
이 버퍼는 프로그램이 출력한 데이터를 모아서 한꺼번에 출력하거나,
입력 장치에서 한번에 많은 데이터를 받아와서 프로그램이 필요한 데이터를 바로 꺼내 쓸 수 있도록 해 줍니다.

그런데 버퍼만 가지고는 저장된 데이터를 관리할 수 없습니다.
데이터를 읽거나 쓸 때 위치도 알아야 하고, 버퍼의 크기도 알아야 하고.. 이러한 추가적인 정보가 필요합니다.
이러한 정보를 갖기 위해 프로그램은 버퍼를 쓰기 전에 정보를 받아 버퍼의 상태를 먼저 파악합니다.
그리고 데이터를 적절하게 입출력하죠.
스트림은 이 정보를 구조체로 묶어서 보관합니다.
이때 스트림 파일이 사용하는 구조체의 이름이 FILE입니다. 예제에도 나왔죠?
따라서 fopen 함수는 메모리에 스트림 파일을 만들고, 이를 쉽게 사용할 수 있도록 FILE 구조체의 주소를 반환합니다.
그러면 FILE* fp;를 통해 쉽게 파일 입출력이 수행되는 겁니다.
이러한 스트림을 사용하면 입출력 효율이 올라가고, 장치로부터 독립적인 프로그래밍이 가능하다는 장점이 있습니다.
3. 텍스트 파일과 바이너리 파일
C 언어에서 파일은 메모리상 연속된 바이트로 저장됩니다.
실제 파일의 저장 내용은 바이트 단위로 기록되며,
이 바이트들을 어떻게 해석할지는 전적으로 프로그래머의 몫입니다.
텍스트 파일(text file)은 사람이 읽을 수 있는 텍스트가 들어 있는 파일입니다.
대표적으로 메모장이 있으며, 이 텍스트 파일은 연속적인 라인(line)으로 구성됩니다.
주로 기준은 줄바꿈 문자 (\n)으로 라인이 갈리지만, 운영체제에 따라 다릅니다.
이진 파일(binary file)은 사람은 못 읽지만 컴퓨터가 읽는 파일입니다.
텍스트 파일과는 다르게 라인으로 분리되지 않아요.
올바르게 해석하기 위해서는 전용 프로그램이나 라이브러리가 필요합니다.
예를 들어, 실행 파일(.exe), 이미지 파일(.png, .jpg), 자바 아카이브(.jar) 등이 이에 해당합니다.