파일 입출력
파일(file)이란?
파일(file)이란 의미 있는 정보를 담고 있으며, 이름을 가지고 있는 저장 장치상의 논리적인 단위를 의미합니다.
C언어에서는 이러한 파일을 바이트별로 따로 읽을 수 있는 연속적인 바이트의 집합으로 취급합니다.
파일의 종류
컴퓨터는 파일을 다음과 같이 두 가지 종류로 나누어서 다룹니다.
1. 바이너리 파일(binary file)
2. 텍스트 파일(text file)
바이너리 파일은 데이터의 저장과 처리를 목적으로 0과 1의 이진 형식으로 인코딩된 파일을 가리킵니다.
프로그램이 이 파일의 데이터를 읽거나 쓸 때는 데이터의 어떠한 변환도 일어나지 않습니다.
텍스트 파일은 사람이 알아볼 수 있는 문자열로 이루어진 파일을 가리킵니다.
프로그램이 이 파일의 데이터를 읽거나 쓸 때는 포맷 형식에 따라 데이터의 변환이 일어납니다.
파일의 입출력
파일의 입출력을 이해하기 위해서는 우선 스트림에 대해 알고 있어야 합니다.
C언어의 스트림에 대한 더 자세한 사항은 C언어 기본적인 입출력 수업에서 확인할 수 있습니다.
C언어에서 콘솔 장치에 대한 스트림은 프로그램 실행 시 자동으로 생성되며, 프로그램 종료 시 자동으로 소멸합니다.
하지만 파일과의 연결을 위한 스트림은 사용자가 직접 생성하고 소멸시켜야 합니다.
C언어에서 파일에 대한 입출력 동작은 다음과 같은 순서에 따라 진행됩니다.
1. 파일과의 스트림 생성
2. FILE 구조체 변수의 포인터를 이용한 작업 진행
3. 파일과의 스트림 종결
fopen() 함수
fopen() 함수는 파일을 열어주는 함수입니다.
파일을 연다는 것은 파일과의 입출력을 위한 스트림을 생성한다는 의미입니다.
fopen() 함수의 원형은 다음과 같습니다.
원형
#include <stdio.h>
FILE *fopen(const char * restrict filename, const char * restrict mode);
fopen() 함수의 첫 번째 인수는 열고자 하는 파일의 이름과 그 경로를 가지고 있는 문자열입니다.
두 번째 인수는 파일을 여는 데 사용할 모드를 지정하는 문자열입니다.
모드 문자열은 파일의 사용 용도를 결정하는 문자열과 파일의 데이터를 어떤 방식으로 입출력할지 결정하는 문자열로 구성됩니다.
모드 문자열
fopen() 함수는 파일을 여는 데 사용할 모드 문자열을 두 번째 인수로 전달받습니다.
이 모드 문자열은 파일의 사용 용도를 결정하고, 파일의 데이터를 어떤 방식으로 입출력할지를 결정합니다.
우선 파일의 사용 용도를 결정하는데 사용할 수 있는 모드 문자열은 다음과 같습니다.
1. r (read mode) : 읽기 전용 모드
2. w (write mode) : 쓰기 전용 모드
3. a (append mode) : 추가 모드
그리고 파일의 데이터를 어떤 방식으로 입출력할지를 결정하는 사용할 수 있는 모드 문자열은 다음과 같습니다.
1. t (text mode) : 해당 파일의 데이터를 텍스트 파일로 인식하고 입출력함.
2. b (binary mode) : 해당 파일의 데이터를 바이너리 파일로 인식하고 입출력함.
또한, 추가적으로 다음과 같은 모드 문자열을 사용할 수 있습니다.
1. x (exclusive mode) : 열고자 하는 파일이 이미 존재하면 파일 개방에 실패함.
2. + (update mode) : 파일을 읽을 수도 있고 쓸 수도 있는 모드
따라서 fopen() 함수에서 사용할 수 있는 모드 문자열의 조합은 다음과 같습니다.
모드 문자열 | 설명 |
---|---|
r | 파일을 오로지 읽는 것만 가능한 텍스트 모드로 개방함. |
w |
파일을 쓰는 것만이 가능한 텍스트 모드로 개방함. 파일이 없으면 새 파일을 만들고, 파일이 있으면 해당 파일의 모든 데이터를 지우고 개방함. |
wx |
파일을 쓰는 것만이 가능한 텍스트 모드로 개방함. 파일이 없으면 새 파일을 만들고, 파일이 있으면 파일 개방에 실패함. |
a |
파일을 쓰는 것만이 가능한 텍스트 모드로 개방함. 파일이 없으면 새 파일을 만들고, 파일이 있으면 해당 파일의 맨 끝에서부터 데이터를 추가함. |
rb |
파일을 오로지 읽는 것만 가능한 바이너리 모드로 개방함. |
wb |
파일을 쓰는 것만이 가능한 바이너리 모드로 개방함. 파일이 없으면 새 파일을 만들고, 파일이 있으면 해당 파일의 모든 데이터를 지우고 개방함. |
wbx |
파일을 쓰는 것만이 가능한 바이너리 모드로 개방함. 파일이 없으면 새 파일을 만들고, 파일이 있으면 파일 개방에 실패함. |
ab |
파일을 쓰는 것만이 가능한 바이너리 모드로 개방함. 파일이 없으면 새 파일을 만들고, 파일이 있으면 해당 파일의 맨 끝에서부터 데이터를 추가함. |
r+ | 파일을 읽고 쓰는 것이 둘 다 가능한 텍스트 모드로 개방함. |
w+ |
파일을 읽고 쓰는 것이 둘 다 가능한 텍스트 모드로 개방함. 파일이 없으면 새 파일을 만들고, 파일이 있으면 해당 파일의 모든 데이터를 지우고 개방함. |
w+x |
파일을 읽고 쓰는 것이 둘 다 가능한 텍스트 모드로 개방함. 파일이 없으면 새 파일을 만들고, 파일이 있으면 파일 개방에 실패함. |
a+ |
파일을 읽고 쓰는 것이 둘 다 가능한 텍스트 모드로 개방함. 파일이 없으면 새 파일을 만들고, 파일이 있으면 해당 파일의 맨 끝에서부터 데이터를 추가함. 읽기는 전체를 읽을 수 있지만, 쓰기는 파일의 맨 끝에만 추가할 수 있음. |
r+b 또는 rb+ | 파일을 읽고 쓰는 것이 둘 다 가능한 바이너리 모드로 개방함. |
w+b 또는 wb+ |
파일을 읽고 쓰는 것이 둘 다 가능한 바이너리 모드로 개방함. 파일이 없으면 새 파일을 만들고, 파일이 있으면 해당 파일의 모든 데이터를 지우고 개방함. |
w+bx 또는 wb+x |
파일을 읽고 쓰는 것이 둘 다 가능한 바이너리 모드로 개방함. 파일이 없으면 새 파일을 만들고, 파일이 있으면 파일 개방에 실패함. |
a+b 또는 ab+ |
파일을 읽고 쓰는 것이 둘 다 가능한 바이너리 모드로 개방함. 파일이 없으면 새 파일을 만들고, 파일이 있으면 해당 파일의 맨 끝에서부터 데이터를 추가함. |
프로그램이 성공적으로 파일을 열면, fopen() 함수는 FILE 구조체 변수의 포인터를 반환합니다.
만약에 해당 파일을 열 수 없으면, fopen() 함수는 널 포인터를 반환합니다.
FILE 구조체 변수의 포인터
FILE 구조체 변수의 포인터는 해당 파일이 사용하는 버퍼 정보를 비롯한 파일에 관한 정보가 들어있는 데이터를 가리킵니다.
따라서 모든 파일 입출력 함수는 FILE 구조체 변수의 포인터를 인수로 전달받아 해당 파일에 접근합니다.
fclose() 함수
fclose() 함수는 파일을 닫아주는 함수입니다.
파일을 닫는다는 것은 파일과의 입출력을 위해 생성한 스트림을 소멸시키는 것을 의미합니다.
즉, 버퍼에 남아있는 데이터를 파일로 완전히 내보내고, 파일 입출력을 위해 내부적으로 생성했던 FILE 구조체를 해제합니다.
C언어에서 다 사용한 파일은 반드시 fclose() 함수를 사용하여 닫아줘야 합니다.
fclose() 함수의 원형은 다음과 같습니다.
원형
#include <stdio.h>
int fclose(FILE *stream);
fclose() 함수는 인수로 닫고자 하는 파일을 가리키는 FILE 구조체 변수의 포인터를 전달받습니다.
이 함수는 파일을 성공적으로 닫으면 0을 반환하고, 해당 파일을 닫지 못했다면 EOF를 반환합니다.
다음 예제는 단순히 파일을 여닫는 동작을 하는 예제입니다.
예제
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
/* 파일 open */
FILE* ptr_file = fopen("example.txt", "w+");
if (ptr_file == NULL) // 파일을 열 수가 없다면, fopen() 함수는 널 포인터를 반환함.
{
puts("파일을 열 수가 없습니다!");
exit(1); // 현재의 C프로그램 자체를 완전 종료하고, 운영체제에 1을 반환함.
}
else
{
puts("파일을 성공적으로 열었습니다!");
}
/* 파일 close */
if (fclose(ptr_file)!=0) // fclose() 함수는 파일을 성공적으로 닫으면 0을 반환함.
{
puts("파일을 닫을 수가 없습니다!");
exit(1);
}
else
{
puts("파일을 성공적으로 닫았습니다!");
}
return 0;
}
실행 결과
파일을 성공적으로 열었습니다!
파일을 성공적으로 닫았습니다!
위의 예제는 모드 문자열로 전달된 "w+"의 정의에 따라, 해당 파일을 쓰는 것만이 가능한 텍스트 모드로 열어줍니다.
이때 파일이 없으면 새 파일을 만들며, 파일이 존재하면 해당 파일의 모든 데이터를 지우고 파일을 열게 됩니다.
따라서 처음 이 프로그램을 동작시키면, 해당 이름의 파일이 존재하지 않으므로 현재 디렉터리에 example.txt라는 파일이 생성될 것입니다.
그 파일에 임의의 문자열을 입력하고 저장한 후, 이 프로그램을 다시 실행시키면 해당 파일의 모든 내용이 지워지는 것을 확인할 수 있습니다.