C언어 초급 - 12장: 파일 입출력 (12.3 바이너리 파일 읽기/쓰기)

2025. 2. 24. 12:02프로그래밍 언어/C

12.3 바이너리 파일 읽기/쓰기

C 언어에서 파일 입출력은 텍스트 파일과 바이너리 파일로 나뉩니다.
바이너리 파일(Binary File)은 텍스트가 아닌 데이터(숫자, 구조체 등)를 그대로 저장하는 파일입니다.

📌 바이너리 파일을 사용하는 이유

  • 데이터를 빠르게 저장하고 읽을 수 있음 (파일 크기가 작고 처리 속도가 빠름).
  • 데이터 손실 없이 그대로 저장 가능 (텍스트 파일은 변환 과정에서 손실 가능).
  • 정수, 실수, 구조체 등의 데이터를 그대로 저장할 수 있음.

바이너리 파일을 처리할 때 fread(), fwrite() 함수를 사용합니다.


1. fwrite() - 바이너리 데이터 쓰기

1.1 fwrite() 함수 개요

fwrite() 함수는 메모리에서 파일로 바이너리 데이터를 저장하는 함수입니다.

📌 문법

size_t fwrite(const void *ptr, size_t size, size_t count, FILE *fp);

📌 매개변수

  • ptr → 저장할 데이터의 주소 (배열, 구조체 등).
  • size → 저장할 데이터 한 개의 크기 (바이트 단위).
  • count → 저장할 데이터 개수.
  • fp → 파일 포인터.

📌 반환값

  • 성공 시 저장된 데이터 개수 반환 (count와 같아야 성공).
  • 실패 시 0 반환.

1.2 fwrite() 사용 예제

#include <stdio.h>

int main() {
    FILE *fp = fopen("data.bin", "wb");  // 바이너리 쓰기 모드

    if (fp == NULL) {
        printf("파일을 열 수 없습니다.\n");
        return 1;
    }

    int numbers[] = {10, 20, 30, 40, 50};  // 정수 배열

    fwrite(numbers, sizeof(int), 5, fp);  // 배열을 파일에 저장

    fclose(fp);  // 파일 닫기
    printf("바이너리 파일 저장 완료\n");

    return 0;
}

출력 결과

바이너리 파일 저장 완료

📌 설명

  • "wb" (write binary) 모드로 파일을 염.
  • fwrite(numbers, sizeof(int), 5, fp);
    • sizeof(int) → 각 정수의 크기(4바이트).
    • 5 → 총 5개의 정수를 저장.
  • 파일에 정수 배열이 바이너리 형태로 저장됨.

텍스트 파일과 다르게 사람이 읽을 수 없는 데이터가 저장됨.


2. fread() - 바이너리 데이터 읽기

2.1 fread() 함수 개요

fread() 함수는 파일에서 메모리로 바이너리 데이터를 읽어오는 함수입니다.

📌 문법

size_t fread(void *ptr, size_t size, size_t count, FILE *fp);

📌 매개변수

  • ptr → 읽어온 데이터를 저장할 변수의 주소.
  • size → 읽어올 데이터 한 개의 크기 (바이트 단위).
  • count → 읽어올 데이터 개수.
  • fp → 파일 포인터.

📌 반환값

  • 성공 시 읽어온 데이터 개수 반환 (count와 같아야 성공).
  • 실패 또는 파일 끝 도달 시 0 반환.

2.2 fread() 사용 예제

#include <stdio.h>

int main() {
    FILE *fp = fopen("data.bin", "rb");  // 바이너리 읽기 모드

    if (fp == NULL) {
        printf("파일을 열 수 없습니다.\n");
        return 1;
    }

    int numbers[5] = {0};  // 데이터를 저장할 배열

    fread(numbers, sizeof(int), 5, fp);  // 파일에서 데이터 읽기

    printf("파일에서 읽은 데이터:\n");
    for (int i = 0; i < 5; i++) {
        printf("%d ", numbers[i]);
    }
    printf("\n");

    fclose(fp);  // 파일 닫기
    return 0;
}

출력 결과

파일에서 읽은 데이터:
10 20 30 40 50

📌 설명

  • "rb" (read binary) 모드로 파일을 염.
  • fread(numbers, sizeof(int), 5, fp);
    • 파일에서 5개의 정수를 읽어와 배열에 저장.
  • 파일에 저장된 데이터가 그대로 복원됨.

바이너리 파일을 사용하면 데이터 손실 없이 원래 값을 그대로 저장하고 읽을 수 있음.


3. 구조체 데이터를 바이너리 파일에 저장

바이너리 파일은 구조체(Struct) 데이터도 그대로 저장할 수 있습니다.


3.1 구조체 데이터를 파일에 저장 (fwrite())

#include <stdio.h>

typedef struct {
    char name[20];
    int age;
    float height;
} Person;

int main() {
    FILE *fp = fopen("people.bin", "wb");

    if (fp == NULL) {
        printf("파일을 열 수 없습니다.\n");
        return 1;
    }

    Person people[2] = {
        {"홍길동", 25, 175.5},
        {"김영희", 30, 162.3}
    };

    fwrite(people, sizeof(Person), 2, fp);  // 구조체 배열 저장

    fclose(fp);
    printf("구조체 데이터 저장 완료\n");

    return 0;
}

3.2 구조체 데이터를 파일에서 읽기 (fread())

#include <stdio.h>

typedef struct {
    char name[20];
    int age;
    float height;
} Person;

int main() {
    FILE *fp = fopen("people.bin", "rb");

    if (fp == NULL) {
        printf("파일을 열 수 없습니다.\n");
        return 1;
    }

    Person people[2];

    fread(people, sizeof(Person), 2, fp);  // 구조체 데이터 읽기

    printf("파일에서 읽은 데이터:\n");
    for (int i = 0; i < 2; i++) {
        printf("이름: %s, 나이: %d, 키: %.1fcm\n", people[i].name, people[i].age, people[i].height);
    }

    fclose(fp);
    return 0;
}

출력 결과

파일에서 읽은 데이터:
이름: 홍길동, 나이: 25, 키: 175.5cm
이름: 김영희, 나이: 30, 키: 162.3cm

📌 설명

  • fwrite(people, sizeof(Person), 2, fp); → 구조체 배열을 바이너리 파일에 저장.
  • fread(people, sizeof(Person), 2, fp); → 저장된 구조체 데이터를 읽어옴.
  • 데이터 변형 없이 원래 상태로 복원됨!

구조체 데이터를 저장할 때 바이너리 파일을 사용하면 변환 과정 없이 빠르고 정확하게 저장할 수 있음.


4. 정리

함수  설명  예제
fwrite() 메모리 데이터를 파일에 저장 (바이너리) fwrite(data, sizeof(int), 5, fp);
fread() 파일에서 데이터를 읽어와 메모리에 저장 fread(data, sizeof(int), 5, fp);
바이너리 파일 모드 "wb" (쓰기), "rb" (읽기) 사용 fopen("file.bin", "wb");
구조체 데이터 저장 구조체 데이터를 바이너리 파일로 저장 fwrite(people, sizeof(Person), 2, fp);

📌 텍스트 파일과 다르게, 바이너리 파일은 사람이 읽을 수 없지만 데이터 손실 없이 저장 가능
📌 fwrite()와 fread()를 사용하면 정수, 실수, 구조체 데이터를 그대로 저장 가능
📌 바이너리 파일은 빠르고, 데이터 손실이 없으며, 파일 크기가 작음