본문 바로가기
개념/혼자 공부하는 C언어

chapter 18) 파일의 형태와 개방 모드가 다른 경우

by kiseno 2024. 10. 15.
728x90
반응형
SMALL
#include <stdio.h>

int main(void){
    FILE *fp;
    int ary[10] = {5,2,3,4,1,6,7,8,9,10};
    int i, res;

    fp = fopen("a.txt", "wb");
    for (i = 0; i< 10; i++){
        fputc(ary[i], fp);
    }
    fclose(fp);

    fp = fopen("a.txt", "rt");
    while(1){
        res = fgetc(fp);
        if (res == EOF) break;
        printf("%4d", res);
    }
    fclose(fp);

    return 0;
}

### 파일 쓰기

- `FILE *fp;`는 파일을 가리키는 포인터 `fp`를 선언합니다.
- `int ary[10] = {5,2,3,4,1,6,7,8,9,10};`는 파일에 쓸 데이터를 저장하는 정수 배열 `ary`를 선언하고 초기화합니다.
- `fp = fopen("a.txt", "wb");`를 사용하여 "a.txt" 파일을 바이너리 쓰기 모드로 엽니다. 파일이 성공적으로 열리면 파일 포인터 `fp`는 열린 파일을 가리킵니다.
- `for` 루프 내에서 `fputc(ary[i], fp);`는 `ary` 배열의 각 요소를 파일에 씁니다. 하지만 `fputc`는 한 바이트 단위로만 데이터를 쓰기 때문에, `int` 타입 데이터를 제대로 처리하지 못하고, `ary`의 각 요소를 정확히 파일에 쓰지 않습니다.
- `fclose(fp);`는 파일 쓰기가 끝난 후 파일을 닫습니다.

### 파일 읽기

- `fp = fopen("a.txt", "rt");`를 사용하여 "a.txt" 파일을 텍스트 읽기 모드로 다시 엽니다.
- `while` 루프 내에서 `res = fgetc(fp);`를 통해 파일로부터 한 바이트씩 데이터를 읽습니다. `fgetc` 함수는 파일의 끝에 도달하면 `EOF`를 반환합니다.
- `if (res == EOF) break;`는 파일의 끝에 도달했는지 확인하고, 그렇다면 루프를 종료합니다.
- `printf("%4d", res);`는 읽은 데이터를 출력합니다. 하지만 바이너리 모드로 쓴 데이터를 텍스트 모드로 읽기 때문에, 데이터가 원래의 의도와 다르게 출력될 수 있습니다.

### 문제점 및 수정 방안

- `fputc`와 `fgetc`는 한 바이트 단위로 데이터를 쓰고 읽습니다. `int` 타입의 배열을 파일에 쓰고 읽기 위해서는 `fwrite`와 `fread` 함수를 사용하는 것이 적합합니다.
- 파일을 쓸 때와 읽을 때 모드를 동일하게 유지해야 합니다. 바이너리 데이터를 처리할 경우, 파일을 열 때 "wb"와 "rb" 모드를 사용하는 것이 일관성 있습니다.

아래는 수정된 코드의 예시입니다:

#include <stdio.h>

int main(void){
    FILE *fp;
    int ary[10] = {5,2,3,4,1,6,7,8,9,10};
    int i, res;

    fp = fopen("a.txt", "wb");
    fwrite(ary, sizeof(int), 10, fp); // 배열 전체를 한 번에 파일에 씁니다.
    fclose(fp);

    fp = fopen("a.txt", "rb");
    while(fread(&res, sizeof(int), 1, fp) == 1){ // 배열의 각 요소를 한 번에 하나씩 읽습니다.
        printf("%4d", res);
    }
    fclose(fp);

    return 0;
}



이 수정된 코드는 `int` 타입의 배열을 파일에 바이너리 형식으로 올바르게 쓰고 읽으며, 원래 의도대로 배열의 각 요소를 정확히 출력합니다.

728x90
반응형
LIST