`fread` 함수

fread 함수 (fread)

이진 데이터를 파일에서 통째로 읽어야 할 때, 문자 단위가 아니라 "구조체 몇 개" 또는 "double 몇 개" 단위로 읽고 싶을 때가 있어요. fread는 그런 요구를 정확히 처리하는 함수예요. 크기와 개수를 따로 받아서 메모리 블록을 그대로 읽어 줍니다.

출처: cppreference

본문

함수 원형

<stdio.h>에 정의돼 있어요.

size_t fread( void* buffer, size_t size, size_t count,
              FILE* stream );                                   // (until C99)
size_t fread( void* restrict buffer, size_t size, size_t count,
              FILE* restrict stream );                          // (since C99)

설명 (Explanation)

주어진 입력 스트림 stream에서 최대 count개의 객체를 buffer 배열로 읽어요. 각 객체마다 fgetcsize번 호출한 것처럼 동작하고, 얻은 결과를 unsigned char 배열로 해석된 buffer의 연속된 위치에 순서대로 저장해요. 스트림의 파일 위치 표시자는 읽은 문자 수만큼 앞으로 이동해요.

오류가 발생하면 스트림의 파일 위치 표시자가 가지는 값은 불확정(indeterminate)이에요. 일부 요소만 읽혔다면 그 요소의 값도 불확정이에요.

매개변수 (Parameters)

  • buffer — 읽은 객체를 저장할 배열을 가리키는 포인터
  • size — 각 객체의 바이트 크기
  • count — 읽을 객체 수
  • stream — 읽어올 스트림

반환값 (Return value)

성공적으로 읽은 객체 수를 돌려줘요. 오류나 파일 끝 조건이 발생하면 count보다 작을 수 있어요.

sizecount가 0이면 fread는 0을 돌려주고 다른 동작은 하지 않아요.

fread는 파일 끝과 오류를 구분하지 않으니, 어떤 일이 있었는지 알려면 호출자가 feofferror로 직접 확인해야 해요.

예제 (Example)

double 배열을 이진 파일에 fwrite로 써 두고, 다시 fread로 읽어들이는 예시예요. 반환값이 기대한 개수와 다른지 확인하면서 오류를 처리해요.

#include <stdio.h>

enum { SIZE = 5 };

int main(void)
{
    const double a[SIZE] = {1.0, 2.0, 3.0, 4.0, 5.0};
    printf("Array has size %ld bytes, element size: %ld\n", sizeof a, sizeof* a);

    FILE* fp = fopen("test.bin", "wb"); // must use binary mode
    fwrite(a, sizeof* a, SIZE, fp); // writes an array of doubles
    fclose(fp);

    double b[SIZE];
    fp = fopen("test.bin","rb");
    const size_t ret_code = fread(b, sizeof b[0], SIZE, fp); // reads an array of doubles

    if (ret_code == SIZE)
    {
        printf("Array at %p read successfully, contents:\n", (void*)&a);
        for (int n = 0; n != SIZE; ++n)
            printf("%f ", b[n]);
        putchar('\n');
    }
    else // error handling
    {
        if (feof(fp))
            printf("Error reading test.bin: unexpected end of file\n");
        else if (ferror(fp))
            perror("Error reading test.bin");
    }

    fclose(fp);
}

가능한 출력:

Array has size 40 bytes, element size: 8
Array at 0x1337f00d6960 read successfully, contents:
1.000000 2.000000 3.000000 4.000000 5.000000

이 예시에서 바이너리 모드("wb", "rb")를 쓰는 이유가 중요해요. 이진 데이터를 다룰 때는 텍스트 모드의 개행 변환이 개입하지 않도록 반드시 바이너리 모드를 써야 해요.

같이 보기 (See also)

  • fgets — 파일 스트림에서 문자열 가져오기
  • fwrite — 파일에 쓰기