C 언어에서 파일 처리(File Handling)란?
파일 처리(File Handling)란 프로그램을 통해 데이터를 파일에 저장하는 작업을 의미합니다. C 프로그래밍에서는 파일 처리 기능을 활용해 프로그램의 실행 결과나 각종 데이터를 파일에 저장할 수 있으며, 반대로 파일에 저장된 데이터를 불러와 프로그램에서 활용하는 것도 가능합니다.
C 언어에서 파일에 대해 수행할 수 있는 주요 연산은 다음과 같습니다.
- 새로운 파일 생성
- 기존 파일 열기
- 기존 파일에서 데이터 읽기
- 파일에 데이터 쓰기
- 파일 내 특정 위치로 이동하여 데이터 처리
- 파일 닫기
fopen() 함수로 파일 생성 및 열기
C 언어에서 fopen() 함수는 새로운 파일을 생성하거나 기존 파일을 여는 데 사용됩니다. 이 함수는 stdio.h 헤더 파일에 정의되어 있습니다.
파일을 생성하거나 여는 기본 문법은 다음과 같습니다.
file = fopen("file_name", "mode")이 문법은 파일을 열 때와 새로 생성할 때 모두 동일하게 사용됩니다.
매개변수 설명
file_name: fopen 메서드로 열거나 생성할 파일의 이름을 지정하는 문자열입니다.
mode: 파일을 어떤 방식으로 열지 지정하는 문자열(보통 한 글자)입니다. C에서는 다양한 모드가 제공되며, 아래에서 자세히 살펴보겠습니다.
언제 파일이 생성되는가?
fopen 함수는 지정된 위치에서 해당 이름의 파일을 찾지 못하면 새 파일을 생성합니다. 반대로 파일이 존재한다면 지정된 모드로 해당 파일을 엽니다.
예를 들어 hello.txt라는 파일을 fopen 함수로 여는 경우를 살펴보겠습니다.
file = fopen("hello.txt", "w")이 코드는 현재 디렉터리에서 hello.txt라는 이름의 파일을 검색합니다. 파일이 존재하면 그 파일을 열고, 존재하지 않으면 "hello.txt"라는 새 파일을 생성한 뒤 쓰기 모드("w")로 엽니다.
파일 열기 모드 종류와 예제
이제 C 언어에서 파일을 읽고 쓸 때 사용할 수 있는 모든 모드를 하나씩 살펴보겠습니다.
모드 "r" — 읽기 전용
읽기 전용으로 파일을 엽니다. 파일 내용을 조회만 할 수 있으며 수정 등 다른 작업은 수행할 수 없습니다.
이 모드는 새 파일을 생성할 수 없으며, 존재하지 않는 파일을 열려고 하면 fopen()이 NULL을 반환합니다.
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("hello.txt", "r")){
printf("File opened successfully in read mode");
}
else
printf("The file is not present! cannot create a new file using r mode");
fclose(file);
return 0;
}
출력 결과:
File opened successfully in read mode
현재 디렉터리에 hello.txt 파일이 있는 경우 위와 같은 성공 메시지가 출력되지만, 존재하지 않는 파일에 접근하면 "The file is not present! cannot create a new file using r mode"라는 메시지가 출력됩니다.
모드 "rb" — 바이너리 읽기 전용
바이너리 모드로 읽기 전용 파일을 엽니다. 내용 조회만 가능하며 수정은 불가능합니다. 역시 새 파일을 생성할 수 없으며, 파일이 없으면 fopen()이 NULL을 반환합니다.
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("program.txt", "rb")){
printf("File opened successfully in read mode");
}
else
printf("The file is not present! cannot create a new file using rb mode");
fclose(file);
return 0;
}
출력 결과:
The file is not present! cannot create a new file using rb mode
모드 "w" — 쓰기 전용
쓰기 전용으로 파일을 엽니다. 파일이 현재 디렉터리에 있으면 쓰기용으로 열고, 없으면 새 파일을 생성합니다. 읽기 작업은 수행할 수 없습니다.
주의할 점은, 기존 텍스트가 담긴 파일을 이 모드로 열면 내용이 모두 덮어씌워진다는 것입니다.
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("helo.txt", "w")){
printf("File opened successfully in write mode or a new file is created");
}
else
printf("Error!");
fclose(file);
return 0;
}
출력 결과:
File opened successfully in write mode or a new file is created
위 예제에서 "helo.txt"는 디렉터리에 존재하지 않지만, 함수가 해당 이름의 파일을 새로 생성했기 때문에 성공 메시지가 출력됩니다.
모드 "wb" — 바이너리 쓰기 전용
바이너리 모드로 쓰기 전용 파일을 엽니다. 파일이 없으면 새로 생성하고, 기존 파일을 열 경우 내용은 덮어씌워집니다.
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("hello.txt", "wb")){
printf("File opened successfully in write in binary mode or a new file is created");
}
else
printf("Error!");
fclose(file);
return 0;
}
출력 결과:
File opened successfully in write in binary mode or a new file is created
모드 "a" — 추가(Append) 전용
추가 전용으로 파일을 엽니다. 파일이 없으면 새로 생성하며, 기존 파일의 내용은 덮어쓰지 않고 파일 끝에 새 텍스트를 덧붙입니다.
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("hello.txt", "a")){
printf("File opened successfully in append mode or a new file is created");
}
else
printf("Error!");
fclose(file);
return 0;
}
출력 결과:
File opened successfully in append mode or a new file is created
모드 "ab" — 바이너리 추가 전용
바이너리 모드로 추가 전용 파일을 엽니다. 파일이 없으면 새로 생성하고, 기존 내용 뒤에 새 데이터를 추가합니다.
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("hello.txt", "ab")){
printf("File opened successfully in append in binary mode or a new file is created");
}
else
printf("Error!");
fclose(file);
return 0;
}
출력 결과:
File opened successfully in append in binary mode or a new file is created
모드 "r+" — 읽기/쓰기 겸용
읽기와 쓰기를 모두 허용하는 모드입니다. 단, 새 파일을 생성할 수 없으며 파일이 없으면 fopen()이 NULL을 반환합니다. 기존 파일에 쓰기를 하면 내용이 덮어씌워집니다.
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("hello.txt", "r+")){
printf("File opened successfully in read and write both");
}
else
printf("The file is not present! cannot create a new file using r+ mode");
fclose(file);
return 0;
}
출력 결과:
File opened successfully in read and write both
모드 "rb+" — 바이너리 읽기/쓰기 겸용
바이너리 모드에서 읽기와 쓰기를 모두 허용합니다. 새 파일을 생성할 수 없으며, 기존 파일에 쓰면 내용이 덮어씌워집니다.
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("program.txt", "rb+")){
printf("File opened successfully in read mode");
}
else
printf("The file is not present! cannot create a new file using rb+ mode");
fclose(file);
return 0;
}
출력 결과:
The file is not present! cannot create a new file using rb+ mode
모드 "w+" — 읽기/쓰기 겸용 (새 파일 생성 가능)
읽기와 쓰기를 모두 수행할 수 있습니다. 파일이 없으면 새 파일을 생성합니다. 기존 파일을 열면 내용이 덮어씌워집니다.
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("helo.txt", "w+")){
printf("File opened successfully in read-write mode or a new file is created");
}
else
printf("Error!");
fclose(file);
return 0;
}
출력 결과:
File opened successfully in read-write mode or a new file is created
존재하지 않는 "helo.txt"를 열었는데도 성공 메시지가 출력된 이유는, 함수가 해당 이름의 파일을 자동으로 생성했기 때문입니다.
모드 "wb+" — 바이너리 읽기/쓰기 겸용
바이너리 모드에서 읽기와 쓰기를 모두 수행할 수 있으며, 파일이 없으면 새로 생성합니다. 기존 파일의 내용은 덮어씌워집니다.
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("hello.txt", "wb+")){
printf("File opened successfully in read-write in binary mode or a new file is created");
}
else
printf("Error!");
fclose(file);
return 0;
}
출력 결과:
File opened successfully in read-write in binary mode or a new file is created
모드 "a+" — 읽기/추가 겸용
읽기와 쓰기(추가)를 모두 수행할 수 있습니다. 파일이 없으면 새로 생성하며, 기존 내용은 덮어쓰지 않고 파일 끝에 새 텍스트를 추가합니다.
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("hello.txt", "a+")){
printf("File opened successfully in read-append mode or a new file is created");
}
else
printf("Error!");
fclose(file);
return 0;
}
출력 결과:
File opened successfully in read-append mode or a new file is created
모드 "ab+" — 바이너리 읽기/추가 겸용
바이너리 모드에서 읽기와 추가를 모두 수행할 수 있습니다. 파일이 없으면 새로 생성하고, 기존 내용 뒤에 새 데이터를 덧붙입니다.
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("hello.txt", "ab+")){
printf("File opened successfully in read-append in binary mode or a new file is created");
}
else
printf("Error!");
fclose(file);
return 0;
}
출력 결과:
File opened successfully in read-append mode or a new file is created
기존 파일에서 데이터 읽기
C 언어에서는 fscanf(), fgets(), fgetc() 함수를 사용해 파일 내용을 읽을 수 있습니다. 각 함수의 동작 방식을 살펴보겠습니다.
fscanf() — 형식화된 문자열 읽기
fscanf() 함수는 파일에서 문자열 등의 데이터를 형식에 맞게 읽어옵니다. 파일의 모든 내용을 다 읽으면 EOF를 반환합니다.
문법:
int fscanf(FILE *stream, const char *charPointer[])
매개변수:
FILE *stream: 열린 파일을 가리키는 포인터
const char *charPointer[]: 문자열 포인터
예제:
#include <stdio.h>
int main(){
FILE * file;
char str[500];
if (file = fopen("hello.txt", "r")){
while(fscanf(file,"%s", str)!=EOF){
printf("%s", str);
}
}
else
printf("Error!");
fclose(file);
return 0;
}
출력 결과:
LearnprogrammingattutorialsPoint
fscanf는 공백을 구분자로 처리하기 때문에 단어들이 붙어서 출력되는 점에 유의하세요.
fgets() — 문자열(줄 단위) 읽기
fgets() 함수는 스트림에서 문자열을 읽어오는 데 사용됩니다.
문법:
char* fgets(char *string, int length, FILE *stream)
매개변수:
char *string: 파일에서 읽은 데이터를 저장할 버퍼
int length: 읽어올 문자열의 최대 길이
FILE *stream: 열린 파일을 가리키는 포인터
예제:
#include <stdio.h>
int main(){
FILE * file;
char str[500];
if (file = fopen("hello.txt", "r")){
printf("%s", fgets(str, 50, file));
}
fclose(file);
return 0;
}
출력 결과:
Learn programming at tutorials Point
fgetc() — 한 문자씩 읽기
fgetc() 함수는 파일에서 한 번에 하나의 문자를 읽어 반환합니다. 파일의 끝에 도달하면 EOF를 반환합니다.
문법:
char* fgetc(FILE *stream)
매개변수:
FILE *stream: 열린 파일을 가리키는 포인터
예제:
#include <stdio.h>
int main(){
FILE * file;
char str;
if (file = fopen("hello.txt", "r")){
while((str=fgetc(file))!=EOF)
printf("%c",str);
}
fclose(file);
return 0;
}
출력 결과:
Learn programming at tutorials Point
C 언어에서 파일에 데이터 쓰기
파일에 데이터를 쓸 때는 fprintf(), fputs(), fputc() 함수를 사용합니다. 각각의 동작 방식을 알아보겠습니다.
fprintf() — 형식화된 데이터 쓰기
fprintf() 함수는 파일에 데이터를 기록하는 데 사용되며, 일련의 문자를 파일에 씁니다.
문법:
int fprintf(FILE *stream, char *string[])
매개변수:
FILE *stream: 열린 파일을 가리키는 포인터
char *string[]: 파일에 쓸 문자 배열
예제:
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("hello.txt", "w")){
if(fprintf(file, "tutorials Point") >= 0)
printf("Write operation successful");
}
fclose(file);
return 0;
}
출력 결과:
Write operation successful
fputs() — 한 줄(문자열) 쓰기
fputs() 함수는 파일에 한 줄(문자열)을 기록하는 데 사용됩니다.
문법:
int fputs(const char *string, FILE *stream)
매개변수:
const char *string[]: 파일에 쓸 문자 배열
FILE *stream: 열린 파일을 가리키는 포인터
예제:
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("hello.txt", "w")){
if(fputs("tutorials Point", file) >= 0)
printf("String written to the file successfully...");
}
fclose(file);
return 0;
}
출력 결과:
String written to the file successfully…
fputc() — 한 문자 쓰기
fputc() 함수는 파일에 단일 문자를 기록하는 데 사용됩니다.
문법:
int fputc(char character , FILE *stream)
매개변수:
char character: 파일에 쓸 문자
FILE *stream: 열린 파일을 가리키는 포인터
예제:
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("hello.txt", "w")){
fputc('T', file);
}
fclose(file);
return 0;
}
출력 결과:
'T' is written to the file.
fclose() — 파일 닫기
fclose() 함수는 열려 있는 파일을 닫는 데 사용됩니다. 파일에 대한 모든 작업이 끝나면 반드시 fclose()를 호출해 변경 사항을 저장하고 리소스를 해제해야 합니다.
문법:
fclose(FILE *stream)
매개변수:
FILE *stream: 열린 파일을 가리키는 포인터
예제:
#include <stdio.h>
int main(){
FILE * file;
char string[300];
if (file = fopen("hello.txt", "a+")){
while(fscanf(file,"%s", string)!=EOF){
printf("%s", string);
}
fputs("Hello", file);
}
fclose(file);
return 0;
}
출력 결과:
LearnprogrammingatTutorialsPoint
작업 후 파일 내용:
Learn programming at Tutorials PointHello
마무리 정리
C 언어의 파일 처리는 fopen()으로 파일을 열고, fscanf/fgets/fgetc 또는 fprintf/fputs/fputc로 데이터를 읽고 쓴 후, fclose()로 파일을 닫는 흐름으로 이루어집니다. 각 모드(r, w, a와 그 조합, b 접미사)의 특성을 정확히 이해하고 사용하면 데이터 손실 없이 안전하게 파일을 다룰 수 있습니다. 특히 "w" 계열 모드는 기존 내용을 덮어쓰므로, 중요한 파일을 다룰 때는 모드 선택에 신중해야 합니다.