프로그래밍 노트

[C]파일의 랜덤 억세스 예제 본문

C++ TIP

[C]파일의 랜덤 억세스 예제

띠리 2008. 5. 28. 14:31
일반적으로 파일을 열고 문자를 파일의 처음부터 순차적으로 읽지만
랜덤 억세스를 하면 처음부터나 파일을 억세스하거나 임의의 위치에서 부터
파일을 억세스할 수 도 있다.


#include <stdio.h>
struct stRec 
{       
    int  iNo; 
    char szName[20];
};
void main() 
{    
    int i;    
    FILE *fp;   
    stRec stMyRec;
    char szNameData[10][20] = {"aa", "bb","cc", "dd", "ee",
                                              "ff", "gg","hh", "ii", "jj"};
 
    // 파일에 구조체 쓰기
    fp = fopen("MyFile.txt", "w");   
    for(i = 1;i <= 10; i++)   
    {     
        stMyRec.iNo = i;
        sprintf(stMyRec.szName, "%s", szNameData[i-1]);
        fwrite(&stMyRec, sizeof(stRec), 1, fp);   
    }   
    fclose(fp);     
    // 파일에서 구조체 읽기
    fp = fopen("MyFile.txt", "r");   
    for(i = 1; i <= 10; i++)   
    {     
        fread(&stMyRec, sizeof(stRec), 1, fp);     
        printf("%d\t%s\n", stMyRec.iNo, stMyRec.szName);   
    }   
    fclose(fp);   
    printf("\n");      
    // fseek를 이용해서 반대로 읽기
    fp = fopen("MyFile.txt","r");   
    for(i = 9; i >= 0; i--)   
    {     
        fseek(fp, sizeof(stRec) * i, SEEK_SET);     
        fread(&stMyRec, sizeof(stRec), 1, fp);     
        printf("%d\n", stMyRec.iNo);   
    }   
    fclose(fp);   
    printf("\n");
    // fseek를 이용해서 두개씩 건너띄기
    fp = fopen("MyFile.txt", "r");   
    fseek(fp, 0, SEEK_SET);   
    for (i = 0; i < 4; i++)   
    {     
        fread(&stMyRec, sizeof(stRec), 1, fp);     
        printf("%d\n", stMyRec.iNo);     
        fseek(fp, sizeof(stRec) * 2, SEEK_CUR);   
    }    
    fclose(fp);   
    printf("\n");
    // 5번째 레코드의 값 바꾸기
    fp = fopen("MyFile.txt", "r+");   
    fseek(fp, sizeof(stRec) * 4, SEEK_SET);   
    fread(&stMyRec, sizeof(stRec), 1, fp);   
    stMyRec.iNo = 55;   
    fseek(fp, sizeof(stRec) * 4, SEEK_SET); 
    fwrite(&stMyRec, sizeof(stRec), 1, fp);    
    fseek(fp, sizeof(stRec) * 0, SEEK_SET);   
    fread(&stMyRec, sizeof(stRec), 1, fp);   
    sprintf(stMyRec.szName, "TEST");
    fseek(fp, sizeof(stRec) * 0, SEEK_SET); 
    fwrite(&stMyRec, sizeof(stRec), 1, fp);    
    fclose(fp);   
    printf("\n");
    // 다섯번째 바뀐 레코드값 표시
    fp = fopen("MyFile.txt", "r");   
    for(i = 1; i <= 10; i++)   
    {    
        fread(&stMyRec, sizeof(stRec), 1, fp);     
        printf("%d\t%s\n", stMyRec.iNo, stMyRec.szName);   
    }   
    fclose(fp);    
}
예제 1 파일 랜덤 엑세스 예제(바이너리 파일)



함수명
형식
처리내용
fseek int fseek(FILE *fp, long offset, int origin) 지정된 위치(orgin 정수)에서 offset만큼 파일 포인터를 이동시킨다.

origin 정수 의미
SEEK_CUR 현재의 팡리 포인터 위치
SEEK_SET 파일의 처음부터
SEEK_END 파일의 마지막 부터

(* 파일 포인터와 파일 구조체의 포인터와 혼동하지 말 것.)
ftell long ftell(FILE *fp) 현재의 파일 포인터(위치)를 반환한다.
rewind void rewind(FILE *fp) 파일 포인터를 그 파일의 선두 위치로 이동시킨다.
테이블 1 랜덤 엑세스 함수





#include <stdio.h>
#include <process.h>
#include <string.h>
#define TOTAL_SIZE 70
int main(void)
{
    int  no, max_no;
    int  nChk;
    int  nKindFile;
    int  nLength;
    long length;
    char name[20], address[30], birth[20];
    char f_name[20], yes_no[16];
    char szFile[20];
    FILE *fp;
    no = 0;
    // 파일 열기
    printf("새 파일:1 , 추가:2 -> ");
    scanf("%d", &nKindFile);
    printf("파일 이름 -> ");
    scanf("%s", szFile);
    if (nKindFile == 1){
        fp = fopen(szFile, "wb");
        if (fp == NULL ) nChk = -1; else no = 1;
    }
    else if (nKindFile == 2){
        fp = fopen(szFile, "rb+");
        if (fp == NULL )
            nChk = -2;
        else{
            fseek(fp, 0L, 0);
            fscanf(fp, "%d", &no);
        }
    }
    // 파일 쓰기
    while(1)
    {
        printf("[No. %d]\n", no);
        printf("이름 -> ");
        scanf("%s", name);
        if (strcmp(name, "E") == 0) break;
        printf("주소 -> ");
        scanf("%s", address);
        printf("생일 -> ");
        scanf("%s", birth);
        nLength = (TOTAL_SIZE) * (no - 1);
        fseek(fp, nLength + 5L, 0);
        fprintf(fp, "%-20s %-30s %-20s", name, address, birth );
        no++;
    }
    fseek(fp, 0L, 0);
    fprintf(fp, "%-5d", no);
    fclose(fp);
    printf("파일이름=");
    scanf("%s", f_name);
    fp = fopen(f_name, "rb");
    if (fp == NULL) {
        printf("에러야");
        exit(-1);
    }
    fscanf(fp, "%d", &max_no);
    while(1) {
        while(1) {
            printf("[No.]=");
            scanf("%d", &no);
            if (no >= max_no || no <= 0)
                printf("번호입력 에러야\n");
            else
                break;
        }
        length = TOTAL_SIZE * (no - 1);
        fseek(fp, length + 5L, 0);
        fscanf(fp, "%20s %30s %20s", name, address, birth);
        printf("이름=%s\n", name);
        printf("주소=%s\n", address);
        printf("생일=%s\n\n", birth);
        printf("계속할꺼야(Y/N)");
        scanf("%s", yes_no);
        if (strcmp(yes_no, "N") == 0)
            break;
    }
    return 0;
}
예제 2 파일 랜덤 엑세스 예제(텍스트 파일)



랜덤 억세스에서 레코드 삭제나 중간에 끼어넣기는 안되는것인가?
인터넷을 나름대로 열심히 찾아봐도 없군 -.-;;
리스트 구조로 가야되는 것인가?

혹시 누가 알면 알려주면 좋으려만...

내가 찾아본 자료로는 랜덤 파일에서 레코드를 삭제하려면
삭제할 레코드를 제외하고 새로운 파일에다가 나머지 레코드를 추가하는 방법을
사용하나보다. 워낙에 랜덤 파일을 이렇게 하는게 정석인 것인가?
Comments