[C] 14. 파일 입출력

Taeil Nam·2022년 6월 21일
0

C

목록 보기
14/18
post-thumbnail

1. 파일 입출력 작동 원리

  • 스트림(Stream) = 데이터가 지나가는 통로.
  • 프로그램과 파일간 운영체제의 도움을 받아 IO 스트림을 통해 데이터를 주고 받음.
  • 텍스트 파일 = 문자로 이루어진 파일.
  • 바이너리 파일 = 2진수로 이루어진 데이터 파일.

2. 텍스트 파일 입출력

코드

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char* argv[])    // Command line 인자 사용.
{
    int ch;
    FILE* fr, * fw;   // 파일을 처리할 때 필요한 구조체(데이터 묶음)에 대한 포인터.

    const char* out_filename = "new_file.txt";	// 파일 출력시 새로 생성되는 텍스트 파일 이름.

    unsigned long count = 0;

    if (argc != 2) // 명령어를 제대로 입력하지 않았을 경우.
    {
        printf("Usage: %s filename\n", argv[0]);
        exit(EXIT_FAILURE); // 프로그램 강제 종료. (return 1)
    }

    if ((fr = fopen(argv[1], "r")) == NULL) // 텍스트 파일을 읽기(r)로 열었을 때 제대로 못 열은 경우.
    {
        printf("Can't open %s\n", argv[1]);
        exit(EXIT_FAILURE); // 프로그램 강제 종료. (return 1)
    }

    if ((fw = fopen(out_filename, "w")) == NULL) // 텍스트 파일을 쓰기(w)로 열었을 때 제대로 못 열은 경우.
    {
        printf("Can't open %s\n", argv[1]);
        exit(EXIT_FAILURE); // 프로그램 강제 종료. (return 1)
    }

    while ((ch = fgetc(fr)) != EOF) // EOF를 만날 때까지 텍스트 파일의 문자를 가져옴
    {
        fputc(ch, stdout);	// 콘솔 창에 문자 출력.
        fputc(ch, fw);		// 새로운 텍스트 파일에 문자 출력.

        count++;    // 문자를 가져올 때마다 count 증가.
    }

    fclose(fr); // 읽기(r)로 열었던 텍스트 파일을 닫아줌. (버퍼에 쌓여있던 데이터를 깔끔하게 처리)
    fclose(fw);	// 쓰기(w)로 열었던 텍스트 파일을 닫아줌. (버퍼에 쌓여있던 데이터를 깔끔하게 처리)

    printf("\nFILE %s has %lu characters\n", argv[1], count);
    printf("FILE copied as %s\n", out_filename);

    return 0;
}

결과


3. 바이너리 파일 입출력

코드

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>

int main()
{
    {   // 1. 바이너리 파일 쓰기.
        FILE* fp = fopen("binary_file", "wb");  // 바이너리 파일을 쓰기(wb)로 열음.

        double d = 1.0 / 3.0;	// 실수형 변수 d 초기화.
        int n = 123;			// 정수형 변수 n 초기화.
        int* parr = (int*)malloc(sizeof(int) * n);	// 포인터 변수 parr에 동적 할당 memory 할당.
        if (!parr) exit(1);		// 동적 할당 오류시 프로그램 강제 종료.
        for (int n = 0; n < 123; ++n)	// n번 만큼 실행
            *(parr + n) = n + 2;		// 동적 할당 받은 memory에 차례대로 값 저장.

        fwrite(&d, sizeof(d), 1, fp);		// 바이너리 파일에 변수 d의 값 쓰기.
        fwrite(&n, sizeof(n), 1, fp);		// 바이너리 파일에 변수 n의 값 쓰기.
        fwrite(parr, sizeof(int), n, fp);	// 바이너리 파일에 포인터 parr의 값 차례대로 쓰기.

        fclose(fp);		// 열었던 바이너리 파일 닫기.
        free(parr);		// 더 이상 사용되지 않는 동적 할당 memory 반납.
    }

    {   // 2. 바이너리 파일 읽기.
        FILE* fp = fopen("binary_file", "rb");  // 바이너리 파일을 읽기(rb)로 열음.

        double d;	// 실수형 변수 d 선언.
        int n = 0;	// 정수형 변수 n 초기화.
        fread(&d, sizeof(d), 1, fp);	// 바이너리 파일의 d 값 읽어옴.
        fread(&n, sizeof(n), 1, fp);	// 바이너리 파일의 n 값 읽어옴.

        int* parr = (int*)malloc(sizeof(int) * n);	// 포인터 변수 parr에 동적 할당 memory 할당.
        if (!parr) exit(1);				// 동적 할당 오류시 프로그램 강제 종료.

        fread(parr, sizeof(int), n, fp);	// 바이너리 파일의 parr 배열 값 읽어옴.

        printf("feof = %d\n", feof(fp));	// 바이너리 파일에서 EOF를 만났는지 확인.

        printf("%f\n", d);	// d 값 출력.
        printf("%d\n", n);	// n 값 출력.
        for (int i = 0; i < n; ++i)
            printf("%d ", *(parr + i));	// parr 포인터 배열 값 출력.
        printf("\n");

        printf("feof = %d\n", feof(fp));	// 바이너리 파일에서 EOF를 만났는지 확인.

        fread(&n, sizeof(n), 1, fp);		// 바이너리 파일에서 n 값을 읽어옴. (더 이상 읽을 데이터가 없으므로 EOF를 만남)

        printf("feof = %d\n", feof(fp));	// 바이너리 파일에서 EOF를 만났는지 확인.
        printf("ferror = %d\n", ferror(fp));	// 바이너리 파일을 읽을 때 에러 발생 유무 확인.

        fclose(fp);		// 열었던 바이너리 파일 닫기.
        free(parr);		// 더 이상 사용되지 않는 동적 할당 memory 반납.
    }
    return 0;
}

결과


4. 파일 임의 접근

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>

int main()
{
    int ch;
    long cur;

    FILE* fp = fopen("input.txt", "r");

    cur = ftell(fp);    // 현재 위치를 나타냄.
    printf("ftell() = %ld\n", cur);

    fseek(fp, 2L, SEEK_SET);    // 시작점(SEEK_SET)으로부터 2 Bytes 떨어진 곳으로 이동.
    cur = ftell(fp);
    printf("ftell() = %ld\n", cur);
    ch = fgetc(fp);             // 현재 위치의 값을 읽고 다음 위치로 이동.
    printf("%d %c\n", ch, ch);
    cur = ftell(fp);
    printf("ftell() = %ld\n", cur);

    fseek(fp, -2L, SEEK_CUR);    // 현재 위치(SEEK_CUR)로부터 -2 Bytes 떨어진 곳으로 이동.
    cur = ftell(fp);
    printf("ftell() = %ld\n", cur);
    ch = fgetc(fp);
    printf("%d %c\n", ch, ch);

    fseek(fp, 0L, SEEK_END);    // 끝 위치(SEEK_END)로부터 0 Bytes 떨어진 곳으로 이동.
    cur = ftell(fp);
    printf("ftell() = %ld\n", cur);
    ch = fgetc(fp);             // 현재 위치의 값(EOF)을 읽고 다음 위치로 이동.
    printf("%d %c\n", ch, ch);  // -1(EOF) 출력.

    return 0;
}

🚩 출처 및 참고자료 : 홍정모의 따라하며 배우는 C 언어 (따배씨)

0개의 댓글