텍스트 파일로 읽고 쓰는 작업을 해 보았으니, 이제는 이진 파일로 동일한 일을 해 볼 시간이에요. 이진 파일은 텍스트 파일만큼 친절하지 않답니다 😉
앞서 배웠던 putc
, fprintf
함수들은 파일에 내용을 문자로 쓰게끔 구현되어 있어요. 다시 말해서, 아스키 값으로 파일에 작성하게 되요. 이렇게 쓴 텍스트 파일은 문서 편집기를 사용해 내용을 직접 눈으로 볼 수 있는 장점이 있으나, 파일의 용량이 커지고, 데이터를 직접 접근하는 데 어려움이 있어요.
만약 마을에 사는 주민들의 명단을 파일에 저장하려 할 때, 텍스트 파일로 저장하면 눈으로 볼 수 있는건 좋지만, 이를 컴퓨터가 읽을 때, fscanf를 사용해 양식에 맞게 정보를 가공해 읽어야 해요. 이는 컴퓨터 입장에서는 번거로운 일이죠.
C언어에서는 이진 파일들을 읽고 쓰는 기능 또한 지원해요.
fwrite 함수의 원형은 아래와 같아요.
size_t fwrite(const void * buffer, size_t size, size_t count, FILE * stream);
fread 함수의 원형은 아래와 같아요.
size_t fread(const void * buffer, size_t size, size_t count, FILE * stream);
이진 파일을 사용하면, 구조체를 파일에 바로 쓰고, 파일에서 바로 읽을 수 있어요. 마을의 주민 명단이 아래와 같을 때, 이 정보를 구조체로 읽어들여 이진 파일로 저장한 후, 이진 파일을 읽어 정보를 콘솔에 표시하는 두개의 코드를 작성할거에요.
주민 명단은 아래와 같아요.
Kildong Hong:20
Minsu Kim:21
Minjae Park:22
fwrite를 사용해, 구조체를 이진 파일에 바로 써볼게요.
#include <stdio.h>
#include <string.h>
#define MAX_NAME_LEN 20
typedef struct resident
{
int age;
char name[MAX_NAME_LEN];
} Resident;
int main(void)
{
FILE *in, *out;
if ( ( in = fopen("resident_list.txt", "r") ) == NULL)
{
fprintf(stderr, "주민 명단을 열 수 없습니다!\n");
return -1;
}
if ( ( out = fopen("resident_list.bin", "wb") ) == NULL)
{
fprintf(stderr, "주민 명단을 쓸 수 없습니다!\n");
return -1;
}
int age;
char name[MAX_NAME_LEN] = {};
while ( fscanf(in, "%[a-zA-Z ]:%d\n", name, &age) != EOF)
{
printf("%s : %d\n", name, age);
Resident r = {.age = age}; // r.age 값만 줘서 구조체 만들기. (C99)
strcpy(r.name, name); // r.name에 이름 저장하기.
fwrite(&r, sizeof(Resident), 1, out);
}
fclose(in);
fclose(out);
return 0;
}
앞서 resident_list.bin 파일에 구조체들을 이진 값으로 저장했으니, 이를 읽어서 콘솔에 출력해볼게요.
#include <stdio.h>
#include <string.h>
#define MAX_NAME_LEN 20
typedef struct resident
{
int age;
char name[MAX_NAME_LEN];
} Resident;
int main(void)
{
FILE *in;
if ( ( in = fopen("resident_list.bin", "rb") ) == NULL)
{
fprintf(stderr, "주민 명단을 열 수 없습니다!\n");
return -1;
}
Resident r;
size_t check = fread(&r, sizeof(Resident), 1, in);
while (check)
{
printf("%s : %d\n", r.name, r.age);
check = fread(&r, sizeof(Resident), 1, in);
}
fclose(in);
return 0;
}