Computer >> 컴퓨터 >  >> 프로그래밍 >> C++

C 프로그래밍 파일 처리 완벽 가이드: fopen부터 fclose까지

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" 계열 모드는 기존 내용을 덮어쓰므로, 중요한 파일을 다룰 때는 모드 선택에 신중해야 합니다.