C 언어에서 데이터를 영구적으로 저장하거나 불러오기 위해서는 파일 입출력 시스템을 이해해야 합니다. 특히 이미지, 음성, 혹은 구조체 데이터를 다룰 때는 바이너리 방식의 fread와 fwrite가 핵심적인 역할을 합니다.
오늘은 파일 입출력의 시작과 끝인 fopen/fclose부터 효율적인 데이터 처리를 위한 fread/fwrite까지 예제와 함께 정리해 보겠습니다.

1. 파일의 문을 여는 fopen & 닫는 fclose
파일 작업의 첫 단계는 fopen으로 파일 포인터를 획득하는 것이고, 마지막 단계는 fclose로 자원을 반납하는 것입니다.
1.1 fopen: 파일 열기
FILE *fopen(const char *filename, const char *mode);
- filename: 열고자 하는 파일의 경로입니다.
- mode: 파일을 어떤 용도(읽기, 쓰기 등)로 열지 결정합니다.
1.2 필수 암기! fopen 모드 정리
| 모드 | 설명 | 비고 |
| "r" / "rb" | 읽기 모드 | 파일이 없으면 NULL 반환 |
| "w" / "wb" | 쓰기 모드 | 파일이 있으면 내용 삭제 후 새로 생성 |
| "a" / "ab" | 추가 모드 | 파일 끝에 데이터를 이어 씀 |
| "r+" / "w+" | 읽기/쓰기 모드 | 기존 파일 수정 또는 새로 생성 |
💡 Tip: 바이너리 데이터를 다룰 때는 모드 뒤에 **'b'**를 붙여(예: "rb", "wb") OS에 따른 줄바꿈 변환 에러를 방지해야 합니다.
1.3 fclose: 파일 닫기
파일을 닫지 않으면 메모리 누수가 발생하거나 데이터가 파일에 제대로 저장되지 않을 수 있습니다.
fclose(fp); // 작업 완료 후 반드시 호출
2. fwrite: 파일에 바이너리 데이터 쓰기
fwrite는 메모리에 있는 데이터를 가공 없이 그대로 파일에 저장합니다. 배열이나 구조체를 통째로 저장할 때 매우 효율적입니다.
예제 코드: 정수 배열 저장하기
#include <stdio.h>
int main() {
FILE *fp = fopen("data.bin", "wb");
if (fp == NULL) {
perror("파일 열기 실패");
return 1;
}
int numbers[] = {10, 20, 30, 40, 50};
// fwrite(데이터주소, 요소크기, 요소개수, 파일포인터)
size_t written = fwrite(numbers, sizeof(int), 5, fp);
if (written == 5) {
printf("데이터 %zu개 쓰기 성공!\n", written);
}
fclose(fp);
return 0;
}
3. fread: 파일에서 바이너리 데이터 읽기
fread는 파일에 저장된 바이너리 데이터를 메모리로 다시 불러옵니다.
예제 코드: 데이터 불러오기
#include <stdio.h>
int main() {
FILE *fp = fopen("data.bin", "rb");
if (fp == NULL) return 1;
int buffer[5];
// fread(저장할주소, 요소크기, 요소개수, 파일포인터)
size_t result = fread(buffer, sizeof(int), 5, fp);
if (result > 0) {
printf("읽어온 값: ");
for(int i = 0; i < 5; i++) printf("%d ", buffer[i]);
}
fclose(fp);
return 0;
}
4. 실무 활용 팁: 구조체(Struct) 단위 입출력
fread와 fwrite의 진가는 구조체를 다룰 때 나타납니다. 복잡한 데이터 형식도 한 번에 읽고 쓸 수 있습니다.
typedef struct {
int id;
char name[20];
} Student;
// 쓰기 예시
Student s1 = {1, "Gildong"};
fwrite(&s1, sizeof(Student), 1, fp);
// 읽기 예시
Student s2;
fread(&s2, sizeof(Student), 1, fp);
5. 마무리하며
C 언어의 파일 입출력은 표준 라이브러리 <stdio.h>를 통해 강력한 제어 기능을 제공합니다.
- 파일 열기 시에는 반드시 성공 여부(NULL 체크)를 확인하세요.
- 작업이 끝나면 fclose를 잊지 마세요.
- 바이너리 데이터는 fread/fwrite를 사용하여 효율적으로 관리하세요.
이 함수들을 잘 활용하면 설정 파일 저장, 게임 데이터 관리 등 다양한 실무 프로젝트를 수행할 수 있습니다.
포스팅이 도움이 되셨다면 하트(♥)와 댓글 부탁드립니다!
임베디드 소프트웨어 및 최적화 기법에 대한 전문적인 정보는 'Coding by Head' 블로그에서 계속됩니다.
'Core Programming > C Standard Library: Resource & Performan' 카테고리의 다른 글
| C언어 파일 포인터 위치 제어: fseek, ftell, rewind 완벽 가이드 (0) | 2025.02.07 |
|---|---|
| C언어 파일 입출력 마스터: fprintf와 fscanf로 데이터 저장 및 읽기 완벽 가이드 (0) | 2025.02.06 |
| C언어 파일 입출력 정복: fputs, fgets 함수 완벽 가이드 (예제 포함) (0) | 2025.02.04 |
| C언어 문자열 입출력 가이드: puts, gets 문제점과 fgets 완벽 대체법 (0) | 2025.02.03 |
| C언어 입출력 완전 정복: stdio.h printf scanf 서식 지정자 총정리 (0) | 2025.02.02 |