97. 바이너리로 파일 입출력

이번에는 메모리를 덤프하는 입출력 함수를 살펴볼게요.

size_t fread(void * buf, size_t element_size, size_t count, FILE * fp);
size_t fwrite(void * buf, size_t element_size, size_t count, FILE * fp);

메모리를 덤프하는 입출력 함수는 내용을 그대로 파일 입출력하는 함수들이예요.
메모리 덤프하는 입출력 함수는 fread와 fwirte 함수가 있어요.
두 함수는 입출력 방향이 메모리에서 파일스트림과 파일스트림에서 메모리라는 점이 다를 뿐이며 함수 원형이 같아요.

두 함수의 입력 인자는 data를 읽거나 쓸 buf의 주소, 요소 크기, 요소 개수, 파일 스트림이예요.
그리고 반환 값은 입출력한 요소 개수를 반환해요.
만약 파일에 있는 내용이 요청한 개수보다 작으면 요청한 개수보다 반환 값이 작을 수 있어요.

회원 관리 프로그램을 예로 들어볼게요.
프로세스가 종료하기 전에 회원 데이터를 저장하고 시작할 때 저장한 회원 데이터를 로딩한다고 가정할게요.
회원 데이터를 배열로 관리한다면 fwrite 한 번 호출로 배열에 있는 전체 회원 정보를 파일에 저장할 수 있어요.
그리고 로딩도 fread 한 번 호출로 가능해요.

#define MAX_MEMBER    50
...중략...
Member members[MAX_MEMBER];
...중략...
void Save()
{
    ...중략...
    fwrite(members,sizeof(Member),MAX_MEMBER,fp);
    ...중략...
};
...중략...
void Save()
{
    ...중략...
    fread(members,sizeof(Member),MAX_MEMBER,fp);
    ...중략...
};

다음은 회원 구조체를 원소로 하는 배열을 파일에 쓰고 읽어오는 것을 테스트 하는 코드예요.

◈ 회원 구조체를 원소로 하는 배열을 파일에 쓰기 및 읽기 테스트

#include <stdio.h>
#define FNAME   "data.txt"
#define MAX_MEMBER    4
#define MAX_NAME_LEN 20
typedef struct _Member Member;
struct _Member
{
    char name[MAX_NAME_LEN+1];
    int num;
};
 
Member src[MAX_MEMBER]=
{
    {"홍길동",1},{"강감찬",4},{"을지문덕",2},{"김구",3}
};
 
Member dest[MAX_MEMBER];
void Save();//src의 회원 정보 파일에 쓰기
void Load();//파일에 회원 정보를 dest로 읽기
void List();//dest 내용 출력
int main()
{
    Save();
    Load();
    List();
    return 0;
}
 
void Save()
{
    FILE *fp = 0;
    fopen_s(&fp, FNAME,"w");
 
    if(fp)
    {
        fwrite(src,sizeof(Member),MAX_MEMBER,fp);
        fclose(fp);
    }
    else
    {
        printf("데이터 저장 실패\n");
    }
}
 
void Load()
{
    FILE *fp = 0;
    fopen_s(&fp, FNAME,"r");
    if(fp)
    {
        fread(dest,sizeof(Member),MAX_MEMBER,fp);
        fclose(fp);
    }
    else
    {
        printf("처음으로 회원 관리 프로그램을 사용을 환영합니다.\n");
    }
}
 

void List()
{
    int i = 0;
    for(i=0;i<MAX_MEMBER; i++)
    {
        printf("이름:%s 번호:%d\n",dest[i].name,dest[i].num);
    }
}

◈ 실행 화면

이름:홍길동 번호:1
이름:강감찬 번호:4
이름:을지문덕 번호:2
이름:김구 번호:3

fwrite 함수를 이용하여 출력한 후에 메모장 프로그램으로 내용을 확인하면 이상한 값이 쓰여진 것처럼 보여요.
메모장 프로그램은 ASCII 문자로 읽어와서 출력하는 프로그램이여서 그렇게 보이는 거예요.
만약 출력한 내용을 다른 프로그램으로 확인하길 원한다면 ASCII 문자로 출력하는 함수를 사용하세요.
하지만 프로그램의 수행 중의 내용을 파일에 보관하고 다음 실행 시에 로드하여 사용할 목적이라면 메모리 덤프로 입출력하는 것이 보다 효과적이예요.