Binary로 저장하고 읽기
❖ fprintf(), fputs(), fscanf(), fgets() 등은 파일에 정보를 문자(Text Mode)로 저장하고 읽는 함수
❖ 메모리에 저장된 Binary 표현 그대 로 메모리에 저장하고 읽기
❖ fread(), fwrite() : Binary 형식으로 읽고 쓰기, 세부 문법은 다음 장에 서 설명
❖ 우측의 코드를 실행 시키고 파일 t1.bin의 내용을 확인하라.
❖ 동일한 파일이라도 Binary Mode 로 해석할 때와 Text Mode로 처리 할 때 큰 차이가 있을 수 있음
2
#include <stdio.h>
int main(void) {
int n1 = 1145258561, n2=0;
float f1 = 781.03522, f2=0;
char ca1[] = {'A', 'B', 'C', 'D', '\0'};
char ca2[] = {0,0,0,0,0};
char buffer[128];
FILE *fp = fopen("t1.bin","w");
fwrite(&n1, sizeof(n1), 1, fp);
fwrite(&f1, sizeof(f1), 1, fp);
fwrite(ca1, sizeof(ca1), 1, fp);
fclose(fp);
fp = fopen("t1.bin","r");
fread(&n2, sizeof(n2), 1, fp);
fread(&f2, sizeof(f2), 1, fp);
fread(ca2, sizeof(ca2), 1, fp);
fclose(fp);
printf("%d %f %s\n", n2, f2, ca2);
fp = fopen("t1.bin","r");
fgets(buffer, sizeof(buffer), fp);
puts(buffer);
fclose(fp);
return 0;
}
Intelligence Networking and Computing Lab.
fwrite, fread 함수
❖ Prototype
▪ size_t fwrite(const void *buffer, size_t
size,
size_tcount,FILE
*stream);▪ size_t fread( void *buffer, size_t
size,
size_tcount, FILE
*stream);• size_t : is the unsigned integer type of the result of sizeof().
• void * : ??
❖ void pointer ?
▪ int main(void)에서
void의 의미는? (매개 변수가) 없음, Nothing
▪ void *
: void의 의미는? 아무것이나, Anything;▪ void *는 아무것(자료형)이나 가리킬 수 있는 pointer : pointer to anything, generic pointer
▪ 우측 코드의 Pointer Assignment를 검토하라
3
void *p1;
int *pn1 = &n1, *pn2;
float *pf1 = &f1, *pf2;
char *pc1 = ca1, *pc2;
pn2 = pn1;
pn2 = pf1;
pn2 = pc1;
p1 = pn1;
p1 = pf1;
p1 = pc1;
warning: assignment from incompatible pointer type pn2 = pf1;
^
warning: assignment from incompatible pointer type pn2 = pc1;
Intelligence Networking and Computing Lab.
void pointer
❖ Pointer 변수에 “*” 연산을 적용하면?
▪ 참조하는(가리키는, 주소를 가지고 있는) 변수를 얻을 수 있음
❖ void *에 대한 “*” 연산?
▪ 참조하는 것이 무슨 Type 인지 알 수 없음. “*” 적용 불가
▪ 우측 코드에서 문제가 발생하는 라인은?
❖ Pointer 변수에 +, - 연산을 적용하면?
▪ 참조 자료형의 크기에 비례하여 주소 값이 증가
▪ void *는 참조하는 자료형의 크기를 알 수 없음
▪ 다음 코드의 첫 출력 값이 0x61FE80일 때 나머지 3개의 주소 값 출력 값은 어떻게 되는가?
4
int
nx = 3, ny;
int
*pnx = &nx;
void
*pvnx = &nx;
ny = *pnx;
ny = *pvnx;
Pointer Variable Variable
&
*
int
nx = 3;
int
*pnx = &nx;
void
*pvnx = &nx;
printf("%p, %p, %p, %p\n", pnx, pnx+1, pvnx, pvnx+1);
fwrite 함수
❖ size_t fwrite(const void *buffer, size _t size, size_t count,FILE *stream);
❖ Buffer는 File로 출력할 대상의 메모리 주 소
▪ void * 로 임의의 자료형을 가리킬 수 있음. 단 자 료형은 의미가 없으며 오직 주소 값만 전달함
▪ 대상의 크기 정보를 알 수 없음
❖ size, count ?
▪ size의 buffer가 가리키는 주소에 있는 단위 객체 자료의 크기
▪ count는 그러한 단위 객체 자료가 몇 개인가를 나 타냄
▪ 결과적으로 size*count Bytes 만큼이 write 됨
❖ Return 값은 성공적으로 쓰인 객체의 수, 실패일 경우 0
❖ 파일에 쓰이는 내용을 기준으로 다음은 동일
▪ fwrite(ca1, sizeof(ca1), 1, fp);
▪ fwrite(ca1, sizeof(char), 5, fp);
▪ fwrite(ca1, 1, sizeof(ca1), fp);
5
#include <stdio.h>
int main(void) {
int n1 = 1145258561, n2=0;
float f1 = 781.03522, f2=0;
char ca1[] = {'A', 'B', 'C', 'D', '\0'};
char ca2[] = {0,0,0,0,0};
char buffer[128];
FILE *fp = fopen("t1.bin","w");
fwrite(&n1, sizeof(n1), 1, fp);
fwrite(&f1, sizeof(f1), 1, fp);
fwrite(ca1, sizeof(ca1), 1, fp);
fclose(fp);
… }
Binary File 쓰기와 읽기 실습 문제
❖ 우측 코드는 rand() 함수를 이용하여 0~9999 사이의 random 정수 1024 개를 생성하여 출력하며 또 그 합을 구하여 출력하는 코드이다.
❖ 우측의 코드를 수정하여 생성한 정 수를 파일 t2.bin에 Binary로 저장하 는 프로그램을 작성하라.
❖ 또한 코드를 참고하여 파일 t2.bin에 서 1024개의 정수를 읽어 그 합을 구하여 출력하는 (별도의) 프로그램 을 작성하라.
❖ 코드 작성 시 새로운 지역 변수를 추 가 하여도 무방하다.
6
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
int main(void) {
int sum=0,i, rval;
srand(time(0));
for (i=0; i<1024; i++) { rval = rand()%10000;
printf("%d ",rval);
sum = sum+rval;
}
printf("\n\nThe Sum == %d\n", sum);
return 0;
}
Intelligence Networking and Computing Lab.
clock() 함수
❖ clock_t clock(void);
▪ Returns raw processor clock time since the program is started.
Returns the approximate processor time used by the process since the beginning of an implementation-defined era related to the program's execution. To convert result value to seconds, divide it by
CLOCKS_PER_SEC.
▪ Only the difference between two values returned by different calls to clock is meaningful, as the beginning of the clock era does not have to coincide with the start of the program.
▪ C Standard Library서 현재 시간을 얻는 함수 time()과 clock()이 있다
▪ time() : returns the current calendar time of the system as time since epoch
❖ 위 함수를 Reference를 보고 이해해 보라
7
B A
파일 쓰기의 성능
❖ 우측 프로그램을 분석해보자.
❖ 코드 블록 A에서는
▪ nd1개의 정수를 random 생성하고 생성한 정 수를 각각 fwrite를 통해 i1.bin에 저장한다.
▪ File 작업 전, 후에 clock()을 이용하여 시간을 구하고 그 차를 통해 처리에 소요된 시간을 출력한다.
❖ 코드 블록 B에서는
▪ 1024개의 정수를 담을 수 있는 array에 1024 개의 정수를 random하게 생성하여 저장한다.
▪ 이러한 array를 fwrite를 통해 i2.bin에 한번에 저장한다. 이를 nd2회 만큼 수행한다.
▪ 이어 A와 유사하게 소요 시간을 출력한다.
❖ 코드 블록 A와 코드 블록 B가 생성하고 저장하는 정보의 양은 다른가?
❖ 이러한 차이의 원인은 무엇일까?
▪ 파일의 읽고 쓰는 단위 ?
▪ 참고 : 4K 단위의 읽기 쓰기
8
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
int main(void) {
int d1, nd1 = 1024*1024*25;
int d2[1024], nd2 = 1024*25;
int i, j;
clock_t t_begin, t_end;
FILE *fp1, *fp2;
srand(time(0));
printf("%ld clock per second\n\n", CLOCKS_PER_SEC);
t_begin = clock();
fp1 = fopen("i1.bin", "wb");
for (i=0; i<nd1; i++) { d1 = rand();
fwrite((void *)&d1,sizeof(int), 1, fp1);
}
fclose(fp1);
t_end = clock();
printf("It takes %ld clocks to write 25M integers\n", t_end-t_begin);
t_begin = clock();
fp2 = fopen("i2.bin", "wb");
for (i=0; i<nd2; i++) { for (j=0; j<1024; j++)
d2[j] = rand();
fwrite(d2,sizeof(int), 1024, fp2);
}
fclose(fp2);
t_end = clock();
printf("It takes %ld clocks to write 25M integers\n", t_end-t_begin);
return 0;
}
구조체의 Binary 쓰기와 읽기
❖ 우측 코드는 구조체 강의에서 다뤘 던 STUD 구조체 변수 s1의 내용을
“t3.bin”이라는 파일에 fwrite()를 이 용하여 Binary 형식으로 저장한 후 다시 해당 파일을 읽어 구조체의 내 용을 변수 s2로 읽어 오는 프로그램 이다.
❖ 프로그램을 실행 시킨 후 생성되는 t4.bin 파일의 크기와 내용 등을 Hexa Viewer를 통해 확인하라.
❖ 구조체 자료형에 대해서도 int, float 등의 단순 자료형과 그 처리 방법론 은 큰 틀에서 같다.
9
#include <stdio.h>
typedef struct student { int id;
char name[12];
double points;
} STUD;
void print_student(STUD *ps) {
if (ps) printf("[%4d:%10s] = %6.2lf\n", ps->id, ps->name, ps->points);
}
int main(void) {
STUD s1 = {1, "Choi", 99.9};
STUD s2 = {2, "Park", 0.1};
FILE *fp = fopen("t3.bin","w");
fwrite(&s1, sizeof(STUD), 1, fp);
fclose(fp);
fp = fopen("t3.bin","r");
fread(&s2, sizeof(STUD), 1, fp);
print_student(&s2);
fclose(fp);
return 0;
}
구조체의 Binary 쓰기와 읽기 – 실습 문제
❖ HW #13 Text Mode 파일 읽기 예
▪ 우측 코드는 HW#12에서 다뤘던 STUD 구 조체에 해당하는 데이터를 포함하고 있는 PNUECS.TXT(홈 페이지 게시) 파일의 데이 터를 main 함수 내의 배열 pnuecs로 읽어 들이고 이후 print_student() 함수를 활용 하여 화면에 출력하는 프로그램이다.
❖ 우측 코드를 수정하여 읽어 들인 데 이터를 Binary 형태로 파일
PNUECS.BIN으로 출력하는 프로그 램을 작성하라.
❖ 추가로 PNUECS.BIN에서 STUD 구조 체를 읽어 들인 후 이를 오름차순으 로 정렬하여 Binary 형태로
PNUECS_Sorted.BIN으로 출력하는 별도의 프로그램을 작성하라.
10
#include <stdio.h>
typedef struct student { int id;
char name[12];
double points;
} STUD;
void print_student(STUD *ps) {
if (ps) printf("[%4d:%10s] = %6.2lf\n", ps->id, ps->name, ps->points);
}
int main(void) {
STUD pnuecs[200];
STUD *ps = pnuecs;
int nps=0,i;
FILE *fp = fopen("PNUECS.TXT","r");
while (fscanf(fp, "%d %s %lf", &ps->id, ps->name,
&ps->points) != EOF) ps++, nps++;
if (nps > 0) {
for (i=0; i < nps; i++) print_student(pnuecs+i);
}
fclose(fp);
// Binary 파일 PNUECS.BIN으로 출력하는 코드 추가 return 0;
}