C 언어 | 고급 기능 | 랜덤 액세스 - fseek(), ftell()
파일의 시작 부분부터 데이터를 읽고 쓰는 방식을 순차 액세스라 하고, 임의의 위치로 이동하여 필요한 부분 만 읽고 쓰는 방식을 랜덤 액세스라고 한다. 여기에서는 표준 C 함수를 사용하여 파일의 임의의 위치에서 데이터를 읽고 쓰는 방법을 설명한다.
임의의 위치를 읽어오기
지금까지의 파일 읽기는 파일의 처음부터 끝까지 순서대로 진행되었다. 파일 함수를 사용하여 가져 오면 파일 위치는 다음 항목에 자동으로 진행되기 때문에, 파일의 시작부터 순서대로 입출력할 수 있었다. 스트림의 다음에 읽고 쓰는 대상의 바이트의 정보를 파일 포인터라고 한다.
파일의 처음부터 순서대로 읽을 파일 형식을 시컨스 액세스라고 한다. 단순한 텍스트 데이터의 경우는 대부분이 순서대로 읽거나 기록하는데 매우 효율적이다. 그러나 바이너리 데이터의 경우는 이 방법만에는 문제가 발생한다.
이진 파일의 경우는 다른 목적의 데이터가 연속하고 있는 것이 많다고 생각된다. 예를 들어, 최초의 16바이트는 위치와 크기, 그 다음에는 4바이트으로 응용 프로그램의 종료 상태를 나타내는 숫자, 그 다음에는 이전의 기동 일시와 같은 상태이다. 이러한 정보는 별도의 파일로 나누는 것보다도, 한번에 모와 버리는 것이 효율적이기에 많은 프로그래머들이 이러한 설계하는 것이다.
그러나 처음부터 20번째 바이트의 어떤 수치만 가져 오려는 것뿐이라면, 지금까지처럼 처음부터 차례로 읽어 들이는 방법은 최적이 아니다. 그래서 바이너리 파일의 경우는 임의의 위치에 접근할 수 있다면 매우 유용하다고 생각된다. 이러한 특정 위치에 파일 액세스를 랜덤 액세스라고 한다.
랜덤 액세스를 실현하려면, 파일 포인터의 위치를 이동시킬 필요가 있다. 지정한 위치에 파일 포인터를 이동 시키려면 fseek() 함수를 사용한다.
fseek() 함수
int fseek( FILE *stream, long offset, int origin );
stream에는 유효한 FILE 형 변수의 포인터를 지정한다. offset에는 origin으로 지정된 위치에서 이동하는 바이트 수를 지정한다. origin에는 stdio.h 헤더에 정의되어있는 다음 상수 중 하나를 지정한다. stream에 지정된 스트림의 파일 포인터는 origin로부터 offset만큼 이동한 위치로 변경된다.
표1 - 탐색(seek) 시작 위치
상수 | 의미 |
---|---|
SEEK_CUR | 현재의 파일 포인터의 위치 |
SEEK_SET | 파일의 시작 |
SEEK_END | 파일 끝 |
반환 값은 성공하면 0을 반환하고, 그렇지 않으면 0이 아닌 값을 반환한다.
만약 현재의 파일 포인터의 위치를 알고 싶어한다면 ftell() 함수를 사용하여 얻을 수 있다.
ftell() 함수
long ftell( FILE *stream);
이 함수는 지정된 스트림의 파일 포인터를 돌려준다.
코드1
#include <stdio.h>
int main() {
char fileName[256];
int fileIndex , text;
FILE *file;
printf("읽을 파일 이름을 지정하십시오>");
scanf("%s" , fileName);
printf("파일을 읽을 시작 위치를 바이트 단위로 지정하십시오.");
scanf("%d" , &fileIndex);
file = fopen(fileName , "rb");
if (file == NULL) {
fprintf(stderr , "파일 조작에 에러가 발생했습니다.\n");
return 0;
}
fseek(file , fileIndex , SEEK_SET);
printf("파일 위치 %d에서 읽습니다--\n" , ftell(file));
while(1) {
text = fgetc(file);
if (feof(file)) break;
printf("%c" , text);
}
printf("\n");
fclose(file);
return 0;
}
코드1을 실행하면 먼저 오픈할 파일 이름을 입력해야 한다. 다음에 지정된 파일이 읽기 시작할 바이트를 지정한다. 예를 들어 100을 지정하면 지정한 파일의 100번째 바이트부터 표시한다. 이 프로그램은 읽어 들인 데이터를 문자로 표준 출력에 출력한다.
코드1은 fseek 함수로 SEEK_SET 즉, 파일의 처음부터 입력된 값 fileIndex 바이트가 나아간 위치에 파일 포인터를 이동시키고 있다. 이렇게 하면 파일 작업을 할 때에 목적하는 특정 값만 얻을 수 있다. 이러한 랜덤 액세스는 바이너리 데이터를 관리할 때 매우 유효하게 될 것이다.