본문 바로가기

not기초/시스템프로그래밍

[시스템프로그래밍]임의 접근 파일

lseek()

  1. 임의의 위치로 파일 위치 포인터를 이동시킬 수 있다
    현재 파일 위치를 whence를 기준으로 offset만큼 이동
  2. prototype
  3. #include <unistd.h>
    off_t lseek(int fd, off_t offset, int whence);

    성공 시 현재 위치, 실패 시 -1 리턴

    파일 위치 포인터
  4. offset : 기준점으로부터 (바이트 단위의) 거리로 이동
    • 양수 : 기준점으로부터 앞으로 이동
    • 음수 : 기준점으로부터 뒤로 이동
  5. whence : 기준점
    • SEEK_SET : 파일의 시작점
    • SEEK_CUR : 현재 파일 위치
    • SEEK_END : 파일의 끝
  6. 파일 위치 포인터 이동 예시
    • lseek(fd, 0L, SEEK_END)
    • lseek(fd, n*sizeof(record), SEEK_CUR)
    • lseek(fd, sizeof(record), SEEK_END) : 레코드 크기만큼 빈공간 생성
  7. dbcreate.c
  8. #define MAX 24
    #define START_ID 1401001
    
    struct stduent {
    	char name[MAX];
    	int id;
    	int score;
    };
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include "student.h"
    
    /*사용자로부터 학번, 이름, 점수를 입력받아 데이터베이스로 구현하는 프로그램*/
    int main(int argc, char *argv[]) {
    	int fd;
    	struct student record;
    	if (argc < 2) {
    		fprintf(stderr, "사용법 : %s\n", argv[0]);
    		exit(1);
    	}
    	if ((fd = open(argv[1], O_WRONLY | O_CREAT | O_EXCL)) == -1) {
    		perror(argv[1]);
    		exit(2);
    	}
    	printf("%-9s %-8s %-4s\n", "학번", "이름", "점수");
    	while (scanf("%d %s %d"), &record.id, record.name, &record.score) == 3){
    		lseek(fd, (record.id - START_ID) * sizeof(record), SEEK_SET);
    		write(fd, (char *)&record, sizeof(record));
    	}
    	close(fd);
    	exit(0);
    }
  9. dbquery.c
  10. #include <stdio.h>
    #include <Stdlib.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include "student.h"
    
    /*사용자로부터 학번은 입력받아 학생 데이터베이스 파일에서
    해당 레코드를 찾아 학번, 이름, 정수를 프린트하는 프로그램*/
    int main(int argc, char *argv[]) {
    	int fd, id;
    	struct student record;
    	if (argc < 2) {
    		fprintf(stderr, "사용법 : %s file\n", argv[0]);
    		exit(1);
    	}
    	if ((fd = open(argv[1], O_RDONLY)) == -1) {
    		perror(argv[1]);
    		exit(2);
    	}
    	do {
    		printf("\n검색할 학생의 학번 입력 :");
    		if (scanf("%d", &id) == 1) {
    			lseek(fd, (id - START_ID) * sizeof(record), SEEK_SET);
    			if ((read(fd, (char *)&record, sizeof(record))) > 0 && (record.id != 0))
    				printf("이름:%s\t학번:%d\t점수:%d\n", record.name, record.id, record.score);
    			else printf("레코드 %d 없음\n", id);
    		}
    		else printf("입력 오류");
    		printf("계속하시겠습니까?(Y/N)");
    		scanf("%c", &c);
    	} while (c == 'Y');
    	close(fd);
    	exit(0);
    }

레코드 수정하기

  1. 레코드 수정 과정
    1. 파일로부터 수정할 레코드 읽기
    2. 메모리에서 레코드 수정
    3. 파일 위치 포인터를 원위치로 변경
    4. 파일 덮어쓰기
  2. dbupdate.c
  3. #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include "student.h"
    
    int main(int argc, char *argv[]) {
    	int fd, id;
    	char c;
    	struct student record;
    	if (argc < 2) {
    		fprintf(stderr, "사용법 : %s file\n", argv[0]);
    		exit(1);
    	}
    	if ((fd = open(argv[1], O_RDWR)) == -1) {
    		perror(argv[1]);
    		exit(2);
    	}
    	do {
    		printf("수정할 학생의 학번 입력: ");
    		if (scanf("%d", &id) == 1) {
    			lseek(fd, (long)(id - START_ID) * sizeof(record), SEEK_SET);
    			if ((read(fd, (char *)&record, sizeof(record))) > 0 && (record.id != 0)) {
    				printf("학번: %8d\t이름: %4s\t점수:%4d\n", record.id, record.name, record.score);
    				printf("새로운 점수: ");
    				scanf("%d", &record.score);
    				lseek(fd, (long)-sizeof(record), SEEK_CUR);
    				write(fd, (char *)&record, sizeof(record));
    			}
    			else printf("레코드 %d 없음\n", id);
    		}
    		printf("계속하겠습니까?(Y/N)");
    		scanf(" %c", &c);
    	} while (c == 'Y');
    	close(fd);
    	exit(0);
    }

#파일_위치_포인터 #lseek() #파일_수정_과정
출처 : 리눅스 프로그래밍, 창병모 저