본문 바로가기

C

([C언어] 21강) 파일 입출력 - 읽기 (fopen, fgets, fseek, feof, fclose)

 

 

이번 강좌에서는 파일 입출력을 배울겁니다.

 

파일 입출력이란 뭘까요??

 

우리는 흔히 텍스트파일, 엑셀파일, 지금은 잘 모르실 제이슨파일 등등

 

많은 종류의 파일을 사용합니다.

 

이 파일들을 읽어서 프로그램에 적용을 시키는것과

 

프로그램에 있는것을 새로 텍스트파일로 저장하는것 두가지를 해볼거고

 

이를 파일 입출력 이라고 하겠습니다

 

입력이란 파일을 읽는거고

 

출력이란 저장하는걸 말하겠죠??

 

자 그럼 오늘은 파일 입출력중 입력에 대해 한번 알아볼까요~?

 

자 우선은 파일을 사용하는법을 알려드리겠습니다.

 

파일을 사용하기 위해서는 fopen함수를 사용해야합니다

 

fopen함수의 사용법은 아래와 같습니다

 

fopen(경로, 모드);

이 코드는 FILE * 형의 값을 반환해줍니다.

 

사용할 파일의 경로와 모드를 넣으면 되는데요

 

경로는 뭐 대충 아실테니 모드를 설명하자면

모드 기능 경로에 해당 파일이  존재하지 않을 경우 경로에 이미 해당 파일이 존재할경우 기존 파일 보호
r 읽기 (입력) 에러 기존 파일 이용 에러
r+ 읽기+쓰기 (출력) 에러 기존 파일 이용 겹쳐써짐
w 쓰기 새로 생성 새로 생성 초기화
w+ 쓰기 + 읽기  새로 생성 새로 생성 초기화
a 쓰기 (덧붙이기) 새로 생성 기존 파일 이용 이어써짐
a+ 쓰기, 읽기 새로 생성 기존 파일 이용 이어써짐

이렇게 나눌수 있습니다

 

자 그럼 한번 파일을 파일을 한번 읽기모드로 열어볼까요?

 

우선 메모장으로 아무 메시지나 넣어보겠습니다!

 

 

자 그럼 이 파일을!

 

 

비주얼 스튜디오의 솔루션 탐색기에서 프로젝트 이름에 마우스 오른쪽 버튼 누르시고

 

파일 탐색기에서 폴더 열기를 누르시면 폴더가 열립니다! 해당 경로에 저장해주세요!

 

이름은 test.txt로 하겠습니다!

 

 

여기까지 잘 되셨나요? 그럼 이제 코드로 한번 읽어보도록 하겠습니다!

 

파일 입출력 함수에는 fscanf와 fprintf등등 많이 있지만 우리는

 

fgets와 fputs를 쓰기로 약속 하겠습니다!

 

우선 fopen함수는 scanf함수처럼 안정성 문제로 비활성화 되었기때문에

 

맨위에 #pragma warning(disable:4996)코드를 추가해주세요

 

#pragma warning(disable :4996)
#include <stdio.h>

int main()
{
    FILE* fs;
    fs = fopen("test.txt", "r");
}

자 이렇게 하면 FILE *형 변수 fs에 test.txt파일이 읽기모드로 열려서 들어가게 됩니다.

 

그럼 이제 어떻게 읽을까요?

 

fgets의 사용법은 아래와 같습니다

fgets(버퍼,읽을 길이,파일);

버퍼에는 char포인터형 즉 char형의 배열을 넣어주면 fgets함수 내에서 버퍼에

 

파일의 내용을 읽어서 넣어줍니다.

 

#pragma warning(disable :4996)
#define MAX_LEN 100
#include <stdio.h>

int main()
{
    FILE* fs;
    fs = fopen("test.txt", "r");
    char str[MAX_LEN];
    fgets(str,MAX_LEN,fs);
    printf("%s",str);
}

실행 결과는!?!?

 

원하던 대로 파일이 잘 읽어져서 나오네요! 그럼 텍스트 파일의 내용을 바꿔보겠습니다

 

이렇게 바꿔볼게요! 다시 실행 해볼까요?

 

엥? 줄바꿈까지도 제대로 된것같은데 "아자차카타파하"라는 글자들이 사라졌네요? 왤까요!

 

scanf함수를 생각해봅시다 scanf는 입력의 끝을 무엇으로 판단하나요?

 

바로 엔터입니다. fgets함수도 엔터를 만나면 입력을 끝으로 알고 엔터까지 출력하고 함수를 종료합니다

 

그럼 다 출력하고 싶다면 어떻게할까요?

 

자 여기서 부터 매우 중요합니다 잘 봐주세요!

 

파일은 파일포인터 라는것으로 이뤄집니다. 파일을 처음 열면 파일포인터는 파일의 시작지점을

 

가리키고 있습니다. 편의를 위해 파일의 내용을 배열로 표시하겠습니다

 

HELLO!!!라고 적힌 파일이 있다면

 

파일포인터는 시작지점을 가리키고 있는것이죠

 

그리고 우리가 fgets함수같은 입력 함수를 써서 3글자 HEL을 읽었다고 칩시다

 

그럼 파일포인터는 세글자 뒤로 움직입니다

 

이렇게 말이죠 그리고 다음번에 다시 fgets함수를 써서 3글자를 읽으면

 

다시 파일포인터는 현재 위치부터 3글자를 알려주고 3글자 뒤 위치로 이동합니다

 

이렇게요! 그래서 fgets함수를 연속해서 쓰면 계속 이어서 읽어주게됩니다.

 

근데 만약에 파일을 읽는 도중에 다시 처음부터 읽고싶다고 칩시다!

 

그럼 어떻게해야할까요?, 파일포인터를 처음 위치로 변경시켜야하는데

 

파일을 새로열기엔 너무 무모한짓 같습니다. 그러면 어떻게 할까요?

 

rewind함수를 쓰면 파일포인터의 위치를 맨앞으로 보낼수 있지만

 

우리는 fseek라는 함수를 사용하도록 하겠습니다

 

fseek함수의 사용법은 아래와 같습니다

 

fseek(파일, 이동할 거리, 이동을 시작할 위치);

이렇게 쓰시면 되는데요! 이동을 시작할 위치는 아래와같이 표시할수있습니다!

 

타입 기능
SEEK_SET 파일의 첫번째 파일 포인터의위치
SEEK_CUR 현재 파일포인터의 위치
SEEK_END 파일의 마지막 파일 포인터의 위치

자 그럼 파일 포인터의 위치를 맨앞으로 바꾸려면 어떻게 쓸까요?

 

fseek(fs,0,SEEK_SET);

이렇게 하면 fs의 파일 포인터가 SEEK_SET즉 첫번째위치로 변경 된 후

 

0칸만큼 이동하니까 첫번째 위치가 되겠네요!

 

또! 파일을 모두 읽었을때는 파일포인터가 SEEK_END위치에 있는지 검사해야하는 경우가 생기는데요

 

그것을 검사해주는 함수가 feof입니다 feof를 사용하면 파일포인터가 마지막에 있는지 검사해주고

 

현재 파일포인터가 마지막이 아닌곳에 있다면 0, 마지막에 있다면 0이 아닌값을 반환해 줍니다!

 

그럼 이를 바탕으로 아까 그 코드를 줄바꿈이 이루어져도 읽을수 있도록

 

바꿔보도록 하겠습니다!

 

#pragma warning(disable :4996)
#define MAX_LEN 100
#include <stdio.h>

int main()
{
    FILE* fs;
    fs = fopen("test.txt", "r");
    while (feof(fs) == 0) {
        char str[MAX_LEN];
        fgets(str, MAX_LEN, fs);
        printf("%s", str);
    }
}

이렇게 하면 while문으로 파일이 끝날때 까지

 

fgets로 파일을 계속 읽어서 화면에 출력해줄테니 줄바꿈이 이루어져도

 

다시읽고 다시읽고 하다가 파일의 끝을 만나서 종료되겠죠!

 

실행 해볼까요?

 

 

성공이네요 그럼 마지막으로 중요한 한가지!

 

파일을 열었으면 파일을 닫는것도 꼭 해주어야합니다!

 

fopen을 했으니 fclose도 해주어야하는건데요

 

꼭꼭 잊지말고 fopen과 fclose는 세트로 생각해주세요!

 

#pragma warning(disable :4996)
#define MAX_LEN 100
#include <stdio.h>

int main()
{
    FILE* fs;
    fs = fopen("test.txt", "r");
    while (feof(fs) == 0) {
        char str[MAX_LEN];
        fgets(str, MAX_LEN, fs);
        printf("%s", str);
    }
    fclose(fs);
}

오늘의 완성 코드입니다!

 

이번시간에는 입력을 배웠으니 다음시간에는 출력을 배워보도록 하겠습니다!

 

다음시간에 봬요~