C언어 입/출력 랜덤 파일 처리

    2018-02-10 05:45:47 작성

    지금까지 파일 입출력을 할때 순차적인 접근을 하여 입출력을 하였습니다.
    경우에 따라서는 파일 중간 또는 끝 부분에 저장된 데이터를 읽어야 하는 경우도 있습니다.
    그러한 경우에 "파일 위치 지시자"를 이동하여 파일을 랜덤으로 입출력 할 수 있습니다.

    FILE 구조체 멤버 중에는 현제 파일을 읽을 위치를 저장하고 있는 멤버가 있습니다.
    이 멤버의 값은 fgets, fputs등의 함수를 호출할 때마다 그 위치가 갱신되어 다음에 읽어드릴 데이터의 위치를 기억하게 됩니다.
    이 위치를 기억하는 멤버를 "파일 위치 지시자" 라고 합니다.

    fseek

    파일위치지시자를 이동합니다.

    int fseek(FILE * stream, long offset, int wherefrom);

    fseek 함수 호출 성공시 0을 반환하고 실패시 0이 아닌값을 반환합니다.
    stream의 파일지시자를 wherefrom 기준에서 offset 만큼 이동하게 됩니다.
    offset은 음수가 올수 있으며 음수일 경우 파일의 앞쪽으로 이동하게 됩니다.
    3번째 매개변수인 wherefrom에 올수 있는 값은 다음과 같습니다.

    wherefrom에 올수 있는 상수 파일 위치 지시자
    0 SEEK_SET 파일의 맨 앞에서부터 이동을 시작
    1 SEEK_CUR 현재 위치에서부터 이동을 시작
    2 SEEK_END 파일의 맨 끝에서부터 이동을 시작
    #include <stdio.h>
    
    int main(void) {
    	FILE * fp = fopen("seektest.txt", "wt");
    	fputs("0123456789", fp);
    	fclose(fp);
    	fp = fopen("seektest.txt", "rt");
    	fseek(fp, -2, SEEK_END); // 위치이동 8
    	putchar(fgetc(fp)); // 8 출력 > 위치이동 +1 = 9
    	fseek(fp, -3, SEEK_CUR); // 위치 이동 9-3 = 6
    	putchar(fgetc(fp)); // 6 출력 > 위치이동 + 1 = 7
    	fseek(fp, 3, SEEK_SET); // 위치이동 0+3 = 3
    	putchar(fgetc(fp)); // 3 출력 > 위치이동 +1 = 4
    	fseek(fp, 2, SEEK_CUR); // 위치이동 4+2 = 6
    	putchar(fgetc(fp)); // 6 출력 위치이동 +1 = 7
    	putchar(fgetc(fp)); // 7 출력 위치이동 +1 = 8
    	printf("\n");
    	fclose(fp);
    	return 0;
    }


    ftell

    현제 파일 위치 지시자의 위치 정보를 반환합니다.

    long ftell(FILE * stream);

    파일위치지시자를 이동하기전 현재 위치를 기억해 둘 필요가 있을때 사용합니다.

    #include <stdio.h>
    
    int main(void) {
    	int i;
    	long curpos;
    	FILE * fp = fopen("telltest.txt", "wt");
    	fputs("1234-", fp);
    	fclose(fp);
    	fp = fopen("telltest.txt", "rt");
    	for (i = 0; i < 4; i++) {
    		putchar(fgetc(fp)); // 현재위치의 숫자를 하나 출력
    		curpos = ftell(fp); // 위치를 기억
    		fseek(fp, -1, SEEK_END); // 끝으로 이동
    		putchar(fgetc(fp)); // - 출력
    		fseek(fp, curpos, SEEK_SET); // 기억한 위치로 이동
    	}
    	printf("\n");
    	fclose(fp);
    	return 0;
    }


    연습문제

    1. 이름과 전화번호를 저장할수 있는 PhoneInfo 구조체를 정의합니다.
    2. 최대 10개의 데이터를 저장할수 있는 PhoneInfo 배열을 선언합니다.
    3. 아래의 그림 처럼 메뉴항목이 나오게 하세요.
    4. 입력을 선택하면 이름과 전화번호를 입력하여 PhoneInfo 배열에 추가합니다.
    5. 목록보기를 선택하면 PhoneInfo 배열에 있는 모든 정보를 출력합니다.
    6. 저장을 종료하면 바이너리파일로 저장합니다.
    7. 종료를 누르면 프로그램을 종료합니다.

    8. 프로그램 시작시 저장된 파일을 읽어 PhoneInfo 배열에 추가합니다.
    파일이 없다면 추가하지 않습니다.