파일의 끝에 도달한 경우 0이 아닌 값을 반환합니다.
int feof(FILE * stream)
파일의 끝을 확인할때 유용하게 사용되는 함수입니다.
다음 예제는 파일을 복사하는 예제입니다.
#include <stdio.h>
int main(void) {
FILE * src = fopen("c:/sample/ezcode.txt", "rt"); // 원본
FILE * des = fopen("c:/sample/ezcode_copy.txt", "wt"); // 사본
char str[30];
if (src == NULL || des == NULL) {
puts("파일 읽기 실패");
return -1;
}
while (fgets(str, sizeof(str), src) != NULL) { // 한줄씩 읽어
fputs(str, des); // 한줄씩 쓴다.
}
if (feof(src) != 0) { // 파일을 끝까지 읽었는지 확인
puts("파일복사 완료!");
}
else {
puts("파일복사 실패!");
}
fclose(src);
fclose(des);
return 0;
}
feof는 파일을 끝까지 도달했는지 확인할때 유용한 함수입니다.
지금까지 텍스트모드에서 읽고 쓰기를 했습니다.
fread 함수와 fwrite 함수는 바이너리 모드에서 입출력할때 사용하는 함수입니다.
size_t fread(void * buffer, size_t size, size_t count, FILE * stream);
fread 함수 호출 성공시 count를 반환하고, 실패 또는 파일 끝에 도달했을때에는 count보다 작은값을 반환합니다.
int buf[20];
fread((void*)buf, sizeof(int), 20, fp);
fp(파일 포인터)로부터 sizeof(int)크기의 데이터를 20개 읽어 배열 buf에 저장하라는 의미입니다.
size_t fwrite(const void * buffer, size_t size, size_t count, FILE * stream);
fwrite 함수 호출 성공시 count를 반환하고, 실패시 count보다 작은 값을 반환합니다.
int buf[5] = {1,2,3,4,5}
fwrite((void*)buf, sizeof(int), 5, fp);
buf 배열에서 sizeof(int)크기씩 5개의 값을 fp(파일포인터)에 쓰라는 의미입니다.
fread, fwrite 함수 모두
1번째 인자를 void* 자료형으로 캐스팅하는데 void 포인터는 무엇이든지 가리킬수 있기 때문에 크기와 관계없이 char형이나 double형 자료형도 전달할 수 있습니다.
2번째 인자는 하나의 값을 입출력할때의 자료형의 크기를 전달합니다.
3번째 인자는 자료형 입출력할 자료형의 개수를 전달합니다.
4번째 인자는 입출력 스트림을 지정합니다.
다음 예제는 이름을 입력받아 바이너리 파일로 저장합니다.
#include <stdio.h>
#include <string.h>
int main(void) {
FILE * fp = fopen("c:/sample/binary.dat", "wb"); // 바이너리 파일 생성
char name[20];
if (fp == NULL) {
puts("파일 읽기 실패");
return -1;
}
do {
printf("종료 END 이름입력 : ");
gets(name);
if (strncmp(name, "END", 3)) { // END 문자열이 아니면
fwrite((void*)name, sizeof(name), 1, fp); //파일에 기록한다
}
else {
puts("파일을 작성하였습니다.");
break;
}
} while (1);
fclose(fp);
return 0;
}
다음은 위에 작성된 파일을 읽어 들입니다.
#include <stdio.h>
int main(void) {
FILE * fp = fopen("c:/sample/binary.dat", "rb"); // 바이너리 파일 읽기
char name[20];
if (fp == NULL) {
puts("파일 읽기 실패");
return -1;
}
while (1) {
// 20byte 1개를 읽어들이지 못하면 탈출
if (fread((void*)name, sizeof(name), 1, fp) != 1) {
break;
}
puts(name);
}
fclose(fp);
return 0;
}
fread 함수와 fwrite 함수를 사용하면 byte단위로 입출력을 할수 있어 구조체 및 배열등을 입출력할때 편리합니다.
서식에 따른 데이터의 입출력을 할 수 있습니다.
fprintf와 fscanf 함수는 첫번째 인자로 스트림을 지정하는것을 제외하고 printf, scanf와 동일하게 작동합니다.
int fprintf ( FILE * stream, const char * format, ... );
int fscanf ( FILE * stream, const char * format, ... );
다음 예제는 구조체를 저장합니다.
#include <stdio.h>
typedef struct _person {
char name[10];
char gender;
int age;
} Person;
int main(void) {
FILE * fp = fopen("c:/sample/ezcode.txt", "wt");
Person person[3] = {
{"홍길동", 'M', 27},
{"임꺽정", 'M', 25},
{"황진이", 'F', 21}
};
int i;
if (fp == NULL) {
puts("파일 읽기 실패");
return -1;
}
for (i = 0; i < 3; i++) {
fprintf(fp, "%s %c %d\n", person[i].name, person[i].gender, person[i].age);
}
printf("파일을 저장하였습니다.\n");
fclose(fp);
return 0;
}
#include <stdio.h>
typedef struct _person {
char name[10];
char gender;
int age;
} Person;
int main(void) {
FILE * fp = fopen("c:/sample/ezcode.txt", "rt");
Person person;
if (fp == NULL) {
puts("파일 읽기 실패");
return -1;
}
while (!feof(fp)) {
fscanf(fp, "%s %c %d\n", person.name, &person.gender, &person.age); // \n은 개행을 읽어 버립니다.
printf("%s %c %d\n", person.name, person.gender, person.age);
}
fclose(fp);
return 0;
}
scanf와 마찬가지로 공백을 구분하여 데이터를 읽어 각 변수에 저장합니다.
1. 위에서 정의한 Person 구조체를 정의합니다.
2. 사용자로부터 3개의 데이터를 입력받습니다.
3. Person 데이터를 바이너리 파일로 저장합니다.
4. 파일에서 Person 데이터를 읽어서 출력합니다.