71.3 파일을 부분적으로 읽고 쓰기

이번에는 fseek 함수를 사용하여 파일 포인터의 위치를 설정한 뒤 파일의 내용을 부분적으로 읽어보겠습니다.

read_partial_file.c

#define _CRT_SECURE_NO_WARNINGS    // fopen 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>     // fopen, fseek, fread, fclose 함수가 선언된 헤더 파일
#include <string.h>    // memset 함수가 선언된 헤더 파일

int main()
{
    char buffer[10] = { 0, };

    FILE *fp = fopen("hello.txt", "r");    // hello.txt 파일을 읽기 모드(r)로 열기.
                                           // 파일 포인터를 반환

    fseek(fp, 2, SEEK_SET);     // 파일 포인터를 파일 처음에서 2바이트만큼 순방향으로 이동시킴
    fread(buffer, 3, 1, fp);    // 3바이트만큼 읽음. 3바이트만큼 순방향으로 이동

    printf("%s\n", buffer);     // llo

    memset(buffer, 0, 10);      // 버퍼를 0으로 초기화

    fseek(fp, 3, SEEK_CUR);     // 파일 포인터를 현재 위치에서 3바이트만큼 순방향으로 이동시킴
    fread(buffer, 4, 1, fp);    // 4바이트만큼 읽음. 4바이트만큼 순방향으로 이동

    printf("%s\n", buffer);     // orld

    fclose(fp);    // 파일 포인터 닫기

    return 0;
}

실행 결과

llo
orld

fopen 함수로 hello.txt 파일을 열고 파일 포인터(읽기/쓰기 위치)를 파일 처음에서 2바이트만큼 순방향으로 이동시켰습니다. 그리고 fread 함수로 3바이트만큼 읽어서 버퍼에 저장합니다.

FILE *fp = fopen("hello.txt", "r");    // hello.txt 파일을 읽기 모드(r)로 열기.
                                       // 파일 포인터를 반환

fseek(fp, 2, SEEK_SET);                // 파일 포인터를 파일 처음에서 2바이트만큼 순방향으로 이동시킴
fread(buffer, 3, 1, fp);               // 3바이트만큼 읽음. 3바이트만큼 순방향으로 이동

버퍼의 내용을 출력해보면 "Hello, world!"에서 순방향으로 2바이트 지점에 있는 "llo"가 나옵니다.

printf("%s\n", buffer);     // llo
그림 71‑6 파일 처음에서 순방향으로 2바이트 지점의 값을 읽음

이제 파일의 파일 포인터를 순방향으로 좀 더 옮겨서 읽어보겠습니다. 먼저 파일을 읽기 전에 memset 함수를 사용하여 버퍼를 0으로 초기화합니다. 그리고 fseek 함수에 3과 SEEK_CUR을 지정하여 파일 포인터를 현재 위치에서 3바이트만큼 순방향으로 이동시키고, fread 함수로 4바이트만큼 읽어서 버퍼에 저장합니다.

memset(buffer, 0, 10);       // 버퍼를 0으로 초기화

fseek(fp, 3, SEEK_CUR);      // 파일 포인터를 현재 위치에서 3바이트만큼 순방향으로 이동시킴
fread(buffer, 4, 1, fp);     // 4바이트만큼 읽음. 4바이트만큼 순방향으로 이동

버퍼의 내용을 출력해보면 "Hello, world!"에서 ", wo"가 나와야 할 것 같은데 "orld"가 나왔습니다. 왜 이렇게 되었을까요?

printf("%s\n", buffer);     // orld

이전에 fread 함수로 3바이트만큼 "llo"를 읽었는데 이렇게 되면 파일 포인터도 3바이트만큼 순방향으로 이동합니다. 따라서 처음 fseek로 2바이트 이동하고, 다시 fread로 3바이트 이동, 마지막으로 fseek로 3바이트 이동하여 파일 처음에서 순방향으로 8바이트(2 + 3 + 3) 지점에 있는 "orld"를 읽게 됩니다.

그림 71‑7 파일 처음에서 순방향으로 8바이트 지점의 값을 읽음

이번에는 파일에 값을 부분적으로 써보겠습니다.

write_partial_file.c

#define _CRT_SECURE_NO_WARNINGS    // fopen 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>     // fopen, fseek, rewind, fread, fclose 함수가 선언된 헤더 파일
#include <string.h>    // strlen, memset 함수가 선언된 헤더 파일

int main()
{
    char *s1 = "abcd";
    char buffer[20] = { 0, };

    FILE *fp = fopen("hello.txt", "r+");    // hello.txt 파일을 읽기/쓰기 모드(r+)로 열기.
                                            // 파일 포인터를 반환

    fseek(fp, 3, SEEK_SET);           // 파일 포인터를 파일 처음에서 3바이트만큼 순방향으로 이동시킴
    fwrite(s1, strlen(s1), 1, fp);    // 문자열 길이만큼 문자열을 파일에 저장

    rewind(fp);                  // 파일 포인터를 파일의 맨 처음으로 이동 시킴
    fread(buffer, 20, 1, fp);    // 20바이트만큼 읽음

    printf("%s\n", buffer);      // Helabcdworld!

    fclose(fp);    // 파일 포인터 닫기

    return 0;
}

실행 결과

Helabcdworld!

먼저 fopen 함수에 "r+"를 지정하여 파일을 읽기/쓰기 모드로 엽니다. 그리고 fseek 함수로 파일 포인터를 파일 처음에서 3바이트만큼 순방향으로 이동시킨 뒤 fwrite 함수로 s1을 파일에 씁니다.

char *s1 = "abcd";

FILE *fp = fopen("hello.txt", "r+");    // hello.txt 파일을 읽기/쓰기 모드로 열기.
                                        // 파일 포인터를 반환

fseek(fp, 3, SEEK_SET);                 // 파일 포인터를 파일 처음에서 3바이트만큼 순방향으로 이동시킴
fwrite(s1, strlen(s1), 1, fp);          // 문자열 길이만큼 문자열을 파일에 저장

다시 파일 포인터를 파일의 맨 처음으로 이동 시킨 뒤 fread 함수로 읽어서 값을 출력해보면 "Helabcdworld!"가 나옵니다.

rewind(fp);                  // 파일 포인터를 파일의 맨 처음으로 이동시킴 
fread(buffer, 20, 1, fp);    // 20바이트만큼 읽음

printf("%s\n", buffer);      // Helabcdworld!

즉, 다음과 같이 "Hello, world!"의 처음부터 순방향으로 3바이트 지점에 "abcd"를 썼으므로 "Helabcdworld!"가 됩니다.

그림 71‑8 파일 처음에서 순방향으로 3바이트 지점에 문자열 쓰기
참고 | fgets, fputs 함수와 파일 포인터의 위치

여기서는 fread, fwrite 함수를 예로 들었지만 fgets, fputs 함수도 읽고 쓴 크기만큼 파일 포인터가 순방향으로(forward) 이동합니다.