[C언어 강좌] #17-1 콘솔 입출력과 파일 입출력


안녕하세요 파일입니다. 오늘은 본격적으로 파일 입출력에 대한 이론과 간단한 예제를 다뤄볼겁니다.

참고로 이번편부터 새롭게 알아야할 개념들이 늘어서 포인터 편처럼 머리가 아파질 수 있습니다..

 

개인적인 느낌으로는 포인터의 경우 개념은 알만했는데 응용이 어렵다면 여긴 개념은 어려운데 응용하는건 그리 어렵지 않습니다.

 

C언어에 대한 고지가 얼마 남지 않았으니 조금만 힘내봅시다. 화이팅!

 

 

콘솔

콘솔(console)은 본래 대형 컴퓨터 시스템과 연결되어 데이터를 입력하는 장치 또는 입력된 데이터를 처리하여 결과를 출력하는 장치를 의미합니다. 여기서의 콘솔은 키보드나 모니터와 같은 표준 입출력 장치를 의미하며, 콘솔 입출력은 키보드에서 데이터를 입력받고 모니터에 데이터를 출력하는것을 말합니다.

 

그렇다면 파일 입출력의 의미는 무엇일까요? 파일 입출력은 파일에서 데이터를 입력받고 파일에 데이터를 출력하는것을 의미합니다. 이번 장에서는 콘솔 입출력과 파일 입출력에 대해서 자세히 알아보겠습니다.

 

스트림이란?

콘솔 입출력과 파일 입출력을 다루기 전 스트림(Stream) 이라는 개념에 대해 알아둘 필요가 있습니다.

 

스트림

스트림(Stream)이란 데이터를 입력하고 출력하기 위한 다리입니다.

지금까지 우리는 scanf() 함수를 이용해서 키보드에서 데이터를 입력받을 수 있었고, printf() 함수를 통해서 모니터에 데이터를 출력할 수 있었습니다.

 

그렇다면 실행중인 프로그램을 통해 어떻게 키보드로부터 데이터를 입력받고, 모니터로부터 데이터를 출력할 수 있는걸까요?

 

표준 입력 스트림과 표준 출력 스트림

다음 그림을 보시면 키보드, 프로그램, 모니터가 있습니다. 서로 완전히 다른 개체입니다. 역할도 전부다르며 심지어 프로그램은 키보드/모니터랑 다르게 SW적인 개념이죠.

 

이들간에 서로 연결을 하려면 어떤 것이 필요할까요? 바로 스트림(다리)이 필요합니다. 즉, 키보드로부터 데이터를 입력하려면 표준 입력 스트림이 필요하고, 모니터로 데이터를 출력하려면 표준 출력 스트림이 필요합니다.

 

* 스트림은 운영체제에 의해서 만들어지는 다리입니다. 하드웨어적인 개념이 아닌 소프트웨어적으로 구현되어 있는 가상의 다리라고 생각하시면 됩니다. 대부분 표준 입출력 스트림의 의미는 키보드와 모니터에 데이터를 입출력하는 다리라고 설명합니다.

 

추가적으로, 스트림은 한 방향으로만 통신할 수 있습니다. (단방향) 그렇기에 입력과 출력을 동시에 처리 할 수 없습니다. => 입력 스트림과 출력 스트림으로 구분되어 있는 이유

 

우리가 프로그래밍을 하면서 스트림 개념에 대해 알아둘 필요는 있지만 어떻게 만드는지 처리과정을 알필요는 없습니다. 운영체제에서 명령을 내리면 알아서 만들어주기 때문입니다.

 

'명령' 이란 것은 우리가 프로그래밍 할때 쓰는 함수같은것으로 내릴 수 있습니다.

특정 함수를 호출하면 컴퓨터가 '아 이함수가 호출됬네? 이런 이런 스트림이 필요하겠구나!' 하고 만들어줍니다.

 

우리는 단순히 만들어진 스트림에서 어떤 데이터가 흘러들어오는지, 어떤 데이터를 흘려보낼건지 결정해주면 됩니다.

예를 들어서 모니터에 무언가를 출력하고 싶으면 만들어진 표준 출력 스트림에 출력할 내용을 보내주면 됩니다. 그러면 모니터에 알아서 출력이 됩니다.

 

C 언어는 콘솔 입출력용으로 표준 입출력 스트림을 제공하는데 printf() 함수나 scanf() 함수가 바로 이들 스트림을 이용합니다. 아래 표는 운영체제마다 공통적으로 제공하는 표준 입출력 스트림을 정리한 것입니다.

 

스트림 설명 장치
stdin 표준 입력을 담당 키보드
stdout 표준 출력을 담당 모니터
stderr 표준 에러를 담당 모니터

 

stdin은 표준 입력 스트림을 가리키는 다리 이름이고, stdout은 표준 출력 스트림을 가리키는 다리 이름입니다. stderr는 표준 에러 스트림을 가리키는 다리이름이며 출력 대상이 모니터이기 때문에 stdout과 같습니다.

 

여기서 궁금한점은 스트림은 sw적으로 구현되어있는 눈에보이지 않는 가상의 다리인데, '가상의 다리 stdin, stdout, stderr은 언제 생성되고 언제 소멸되는가?' 입니다. 

 

운영체제는 stdin, stdout, stderr와 키보드와 모니터로 연결하기 위해 프로그램 시작 시 스트림을 생성하고, 프로그램 종료 시 스트림을 자동 소멸시킵니다.

 

지금까지 별 생각없이 사용한 scanf() 함수와 printf() 함수와 같은 콘솔 입출력 함수는 바로 stdin(키보드)과 stdout(모니터) 스트림들을 이용하여 입출력이 된 것 입니다. 다음 그림은 지금까지 설명한 내용을 도식화한 것입니다.

 

스트림(다리)의 이름이 각각 stdin, stdout이라고 설명드렸으므로 위와 같이 나타납니다.

 

그런데 입출력할 대산이 키보드, 모니터가 아니라 파일이라면 어떤 스트림을 이용해야 할까요?

즉, 프로그램에서 입력해야 할 데이터를 키보드에서 가져오는 것이 아니라 파일에서 가져오고,

데이터를 모니터에 출력하는것이 아니라 파일에 출력하려면 어떤 스트림을 통해야 하는지 입니다.

 

해결을 위해선 파일 입출력 스트림을 이용하면 됩니다.

그림으로 나타내면 아래와 같습니다.

 

입출력을 파일로 받으므로 양옆이 파일로 바뀌었고 사용하는 스트림이 달라졌다는 것 정도밖엔 차이가 없습니다.

 

버퍼와 버퍼링

컴퓨터 분야에서 버퍼(Buffer)는 처리할 데이터를 임시로 저장하는 저장소 입니다. 데이터 생성 속도와 데이터 처리 속도가 다를경우 속도 차이를 메워 주기 위한 임시 저장공간으로써 역할을 합니다.

 

방금전에 사용한 이 그림에서 프로그램 내부를 조금더 자세히 들여다 보아 입출력을 어떤식으로 처리하는지 알아보겠습니다. 

 

해당 그림처럼, 버퍼에는 입력버퍼와 출력버퍼가 있습니다. 입력버퍼는 입력데이터를 저장하기 위한 버퍼이며, 출력 버퍼는 출력 데이터를 저장하기 위한 버퍼입니다. 

입력 버퍼와 출력 버퍼를 사용하는 함수들이 바로 표준 입출력 함수입니다.

 

우리가 키보드를 통해서 입력한 데이터는 입력 스트림을 통해 입력 버퍼에 임시로 저장되고,  printf() 함수를 호출해서 모니터에 데이터를 출력하기 위해 먼저 출력 버퍼에 저장되어서 출력 스트림을 통해 모니터에 출력됩니다.

 

컴퓨터 분야에서 버퍼링이란 버퍼를 활용하는 방식 또는 버퍼를 채우는 동작을 말합니다. 보통 키보드와 같은 입력 장치로부터 데이터를 받거나 프린터와 같은 출력 장치로 데이터를 전송할때 버퍼 안에 임시 저장됩니다. 버퍼링을 하는 이유는 바로 성능 향상을 위해서 입니다.

 

문자를 하나씩 처리하는 것보다는 문자들을 한꺼번에 모아서 한꺼번에 처리하는것이 더 효율적일 수 있습니다. 일상적인 예로써 공사장에서 벽돌을 손으로 하나씩 운송하는것보단 큰 수레와 같은 임시 저장 공간을 빌려서 한꺼번에 많은 양의 벽돌을 운송하는게 훨씬 더 효율적일 것입니다.

 

스트림 기반으로 입출력을 하는 경우에 입출력 처리를 위해 버퍼를 사용하고, 버퍼링을 통해 데이터를 한꺼번에 담고 처리하면 효율적으로 입출력 처리가 가능합니다.


우리가 유투브를 보면서 '버퍼링 걸린다' 라는 말을 한적이 많을겁니다. 지금 버퍼링이 바로 그것인데요. 스트리밍 기술이 생기면서 우리는 영상을 통째로 다운받지 않아도 영상을 볼 수 있게 되었습니다.

스트리밍 기술의 원리는 영상을 조각조각 나눠서 다운 받아 보는것입니다. 이렇게 작은 조각을 다운로드해서 버퍼에 담는것, 이것을 버퍼링이라고 하는 것 입니다.

 

처음에 버퍼링 과정을 거쳐서 우선 영상을 재생하고, 그 다음 부분을 계속 재생하기 위해 작은 조각으로 다운로드를 계속 진행(버퍼링을 진행)합니다. 만약에 인터넷 속도가 빨라서 작은 단위를 재생시간보다 빠르게 다운로드 할 수 있다면(버퍼링이 빨리 이루어진다면) 다음으로 매끄럽게 이어지면서 영상이 끊김없이 재생될 것 입니다만,

 

만약에 이 버퍼링 과정이 인터넷 속도가 느려져서 다음 재생시간에 맞춰서 다 받지 못한다면 유투브에 로딩바가 뜨면서 우리가 흔히 말하는 '버퍼링 걸린다' 라는 과정이 이루어질 것 입니다.

 

콘솔 입출력

앞에서 말했듯이 콘솔은 키보드나 모니터와 같은 표준 입출력 장치를 의미합니다. 즉, 콘솔 입력 장치인 키보드, 콘솔 출력 장치인 모니터를 의미합니다.

C언어에서는 키보드로부터 데이터를 입력받고, 모니터에 데이터를 출력하기 위해서 제공되는 콘솔 입출력 함수가 있습니다.

 

지금부터 콘솔 표준 입출력 함수와 콘솔 비표준 입출력 함수 둘의 차이를 알아보겠습니다.

 

콘솔 표준 입출력 함수

아래는 콘솔 표준 입출력 함수를 정리한 것입니다. 콘솔(키보드, 마우스)을 이용해 데이터를 읽어 들이거나 출력하는 함수들 입니다. 콘솔 표준 입출력 함수를 그냥 표준 입출력 함수라고도 합니다.

 

stdio.h 가 standard input output 의 줄임말이란것 기억나시나요?

영어 뜻 그대로 표준 입출력 함수라고 부르는 이유입니다.

 

표준 입출력 함수 사용을 위해선 이름에도 친절하게 나와있지만 stdio.h 를 인클루드 하면 됩니다.

 

또한 콘솔 표준 입출력 함수버퍼를 사용하는 함수라는 특징이 있습니다.

함수 원형 설명
int getchar(void); 키보드로부터 문자 한개를 입력받음
int putchar(int c); 모니터에 문자 한개를 출력
char * gets(char * s); 키보드로부터 문자열 입력
int puts(char * str) 모니터에 문자열 출력
int scanf(const char * format, ...); 키보드로부터 데이터를 서식에 맞추어 입력
int printf(const char * format, ...); 모니터에 데이터를 서식에 맞추어 출력

 

콘솔 입출력 함수는 키보드로부터 데이터를 입력받고, 모니터에 데이터를 출력하기 위해 제공되는 함수라고 했습니다.

 

(콘솔) 표준 입출력 함수는 우리가 지금까지 흔히 써왔던 printf(), scanf()와 문자열 편에서 새로 배운 gets()와 puts() 가 있습니다.

 

많이 사용해봤고 이미 친숙할것입니다.

이번엔 새로 배우는 getchar() 함수와 putchar() 함수만 알아보겠습니다.

 

getchar() 함수는 gets() 함수의 한글자 버전, 즉 문자 버전이라고 보시면 됩니다. getchar() 함수는 사용자가 키보드로부터 문자를 입력할때까지 기다리고 있다가 Enter 키를 입력하면 입력 문자 중 첫 번째 문자의 키 값을 int형으로 변환합니다. 

 

여기서 키 값은 당연히 ASCII 코드 값이고 왜 char이 아니라 int형으로 반환하냐고 하면 입력하는 중에 에러가 발생하면 EOF를 반환합니다. EOF는 파일의 끝을 의미하는 매크로 상수로 stdio.h 에 -1로 정의되어있다고 했습니다.

(EOF == -1)

 

getchar() 함수를 통해 키보드 입력 중에 에러가 발생한다는 것은 컴퓨터 시스템이 정상적으로 동작하지 못하는 경우이므로 일일이 EOF 반환 여부를 검사할 필요는 없습니다. EOF가 주로 사용되는 경우는 키보드로 데이터를 입력할때 입력의 끝을 알리기 위해 시스템에게 여기가 입력의 끝이다는 것을 알리는 역할을 하는 경우입니다.

 

데이터 입력중에 Ctrl + Z 를 단축키로 입력하면 데이터 입력을 끝낸다는 의미와 같습니다.

 

putchar() 함수의 경우에도 puts()의 한글자 버전이라고 생각하시면 됩니다. putchar() 함수는 출력 기능도 있지만 int값을 반환하기도 하는데 역시 getchar()과 마찬가지로 출력중에 에러가 발생하는 에러를 알리기 위한 목적으로 호출 실패시 EOF를 반환하기 위해서입니다. 출력 중에 에러가 발생하는 경우 컴퓨터 시스템이 정상적으로 동작하지 않는 상황으로 putchar() 함수의 결과값도 일일히 검사할 필요는 없습니다.

 

putchar() 함수의 경우 printf("%c") 로 그 기능을 대신할 수는 있지만, 문자 단위의 출력은 putchar() 함수가 printf() 함수보다 훨씬 빠르고 효율적으로 동작합니다.

#include <stdio.h>


int main(){
	char ch = 0;
	
	while(ch != EOF){ //==while(ch != -1)
		ch=getchar();
		putchar(ch);
	}
	return 0;
}

a
a
b
b
c
c
d
d
e
e
f
f
^Z

--------------------------------
Process exited after 3.557 seconds with return value 0
계속하려면 아무 키나 누르십시오 . . .

 

다음 예제는 getchar() 과 putchar()을 사용하는 예제입니다.

한글자이므로 char 자료형으로 써야합니다.

 

일반적으로 ch=getchar()로 값을 받을때 키보드 입력중에 오류가 발생할때만 EOF가 발생합니다만, 컴퓨터에 문제가 있을때만 이렇고 아까도 말했듯이 Ctrl + Z 를 하면 EOF를 발생시켜서 반복문을 종료시킬 수 있습니다.

 

Ctrl+Z 를 입력값으로 주자 EOF라고 인식되어 반복문이 종료된 모습입니다ㅣ.

 

콘솔 비표준 입출력 함수

지금 아래에 나열된 함수들은 콘솔 비표준 입출력 함수버퍼를 사용하지 않는 다는 특징이 있습니다. ANSI C표준은 아니지만 대부분의 C컴파일러가 지원하는 직접 문자 입력 함수로 콘솔(키보드, 모니터)을 이용해 데이터를 읽어 들이거나 출력합니다. 이들 함수를 사용하려면 헤더파일 conio.h를 인클루드 해야 합니다.

 

*conio.h = console and port I/O

 

함수 원형 설명
int getch(void); 키보드로부터 한 문자를 입력받음(입력 화면에 입력 문자가 보이지 않음)
int getche(int c); 키보드로부터 한 문자를 입력받음(입력 화면에 입력 문자가 보임)
int putch(int c); 모니터에 한 문자를 출력
int kbhit(void); 키보드에 키가 눌려졌는지를 조사(누른 경우 0이 아닌 수를 반환합니다.)

*사용을 위해 <conio.h> 를 인클루드 해야 합니다.

 

getch() 는 아까봤던 getchar()과 닮았고 getche()는 getch 끝에 알파벳 e만 추가한 형태네요.

putch() 경우에도 putchar() 과 비슷한 느낌이 듭니다.

 

getch() 함수와 getche() 함수는 문자의 입력을 담당하는 비표준 입력 함수입니다. 두 함수의 유일한 차이가 있다면 getch() 함수는 사용자가 입력한 문자를 화면에 보여주지 않지만 getche() 함수는 사용자가 입력한 문자를 화면에 보여줍니다. 

 

putchar() 함수는 문자의 출력을 담당하는 비표준 출력 함수이며 kbhit() 함수는 키보드의 키가 눌려졌는지를 조사하는 비표준 키 입력 함수입니다. (kbhit == keyboardhit)

 

#include <stdio.h>
#include <conio.h>

int main(){
	char ch = 0;
	printf("키 입력 : ");
	
	while(ch != 'q')
	{
		if(kbhit()){
			ch=getche();
			putch(ch);
		}
	}
	return 0;
}

키 입력 : HHEEllllooqq
--------------------------------
Process exited after 0.8721 seconds with return value 0
계속하려면 아무 키나 누르십시오 . . .

비표준 입출력 함수들은 내부적으로 버퍼를 사용하지 않는 다는 차이점 이외에 사용할때는 표준 입출력 함수랑은 크게 차이가 없습니다. (물론 버퍼와 연관된 조작이 필요할경우 표준 입출력 함수를 사용해야 합니다.)

 

getch()는 getchar() 과 거의 동일하니 getche()만 특별히 써보았습니다.

 

키를 입력할때 보시면 메아리를 치듯이 키가 두번씩 나오는걸 볼 수 있습니다.

제가 입력한게 그대로 콘솔창에 한번더 보이는 것 입니다.

 

*.bat을 이용해서 배치 파일을 만들때 @echo off 를 넣어주는게 이 메아리를 없애기 위해서 입니다.

(크게 중요하진 않으니 잘 모르시면 넘어가시면 됩니다.)

 

추가적으로, 비표준 입출력 함수들은 버퍼를 사용하지 않기 때문에 표준 입출력 함수들에 비해 속도가 빠릅니다. 그러나 여러 개의 문자를 처리하거나 데이터를 일괄해서 처리하는 경우에는 표준 입출력 함수를 사용하는 것이 좋습니다.

 

파일 입출력

지금까지 표준 입출력 함수와 비표준 입출력 함수에 대해 알아보았습니다. 이제부터는 본격적으로 파일 입출력에 대해 알아봅시다.

 

지금부턴 제 닉네임과 관련된 내용들이 쏟아져 나올 것 입니다.

 

파일 입출력의 중요성

파일 입출력이 필요한 이유는 무엇일까요? 지금까지 우리가 작성한 프로그램에서는 프로그램 실행 중에 데이터가 만들어지면 데이터를 메모리에 보관해서 사용했습니다. ex) 변수 등등

그러나 메모리(RAM)에 저장된 데이터는 프로그램이 종료되면 사라지게 됩니다.

 

만일 프로그램 실행 중에 만들어진 데이터를 프로그램이 종료된 후에도 계속해서 사용하려면 어떻게 해야 할까요? 이때 파일이 사용됩니다. 프로그램이 종료되면 관련 데이터들이 소멸해버리지만, 프로그램에서 중요한 정보를 HDD/SSD 와 같은 저장장치에 파일로 기록해놓으면 사라지지 않고 남아있으며, 필요할 때 파일을 읽어서 데이터를 불러올 수 있습니다.

 

파일은 프로그램이 디스크에 데이터를 기록하는 단위로 일정한 종류의 데이터를 미리 정한 원칙에 따라 정리하고 있는 것이라고 생각하시면 됩니다. 컴퓨터를 써봤다면 '파일' 정말 많이 들어본 개념이기도 하고 제 닉네임이기도 합니다.

이번장에서 중요한건 'C언어로 파일 입출력을 어떻게 다루는가?' 입니다.

 

우리가 사용하는 파일은 다음과 같이 두 가지 유형으로 나누어집니다.

 

1. 텍스트 파일 : 일반 문서 편집기에서 문서를 열어 데이터 내용을 확인할 수 있는 문자들을 저장해놓은 파일

즉, 문자열과 같은 텍스트 기반의 데이터 파일을 의미합니다.

 

2. 바이너리 파일 : 바이너리 데이터(이진 데이터)를 저장하는 파일로 일반 문서 편집기에서는 내용을 확인할 수 없습니다. 바이너리 파일은 이진 파일이라고도 부르며 컴퓨터 파일로 이진 형식(0과 1로만 이루어진)으로 인코딩된 데이터를 의미합니다.

만약 바이너리 파일을 텍스트 모드로 열면 글자가 전부 깨져서 출력됩니다.

 

자세한 내용 :  https://blog.naver.com/tipsware/221353023593

 

 

텍스트 파일과 바이너리 파일에 대하여!

: C 언어 관련 전체 목차 http://blog.naver.com/tipsware/221010831969 1. 바이너리 파일이란? 우리가 많...

blog.naver.com

 

간단하게 정리하여, 메모장과 같은 프로그램으로 문자열로 읽히는 파일들이 텍스트 파일이고 이외 0,1로 이루어진건 전부 바이너리 파일입니다. 이런것들은 hxd와 같은 유틸리티를 사용하면 볼 수 있습니다.

파일 출력 맛보기

보통 강의를 진행하면서 선이론-후실습 또는 선실습-후이론의 형태로 진행했으나 이번 파일 입출력 파트는 선이론-후실습으로 진행할것입니다.

 

그런데 선이론에 있어서 내용이 상당히 길어질 거 같아 우선 파일 출력을 소스코드로 어떻게 작성하는지 감을 잡고 가는게 좋을거 같아서 파일 출력 실습을 먼저 간단하게 해보고 이론에 대해 알아보겠습니다.

 

#include <stdio.h>

int main(){

  FILE *fp = fopen("newfile.txt", "w");
  fputs("hello c world", fp);
  fclose(fp);
    	
	return 0;
}

제일 처음 printf("Hello World") 할때 배웠던 방식 기억 나시나요?

일단 내용은 무슨소린지 모르겠어도 그냥 따라쓰고 나중에 배웠었죠.

오늘도 그렇게 해볼겁니다. 위에 소스코드를 복붙하시던가 직접 타이핑한 후 실행해보세요. (개인적으로 직접 타이핑 추천드립니다.)

 

실행하면 당연히 콘솔창에 아무것도 안나올겁니다. printf() 같은 콘솔 출력함수는 일체 사용하지 않았으니깐요. 그런데 파일 입출력 함수는 사용했습니다. (여기서 뭐가 파일 입출력 함수인지 막 찾지 않으셔도 됩니다. 이후에 설명드릴거니깐요.)

 

실행한 c언어 파일과 동일경로에 가보시면 newfile.txt 라는 파일이 생성되었고 

 

 

파일을 열어보면 위처럼 내용도 잘 들어가 있는걸 볼 수 있습니다.

지금까진 콘솔에서 놀았지만 파일이 만들어지니 매우 신기하죠..? (신기해야 합니다 ㅎㅎ..)

 

파일을 이용한 입출력 과정

방금전에 배웠던 내용을 복습해보자면, 스트림은 운영체제에 의해 만들어지는 다리이며, 소프트웨어적인 개념으로 구현되어 있는 가상의 다리라고 했습니다.

 

키보드, 프로그램, 모니터 각기 다른 특징을 가진 개체들을 이어주는 다리가 바로 스트림이라고 했었죠.

꼭 위 3가지가 아니여도 여러가지 스트림이 있으며 운영체제가 처리를 해줍니다.

 

예를 들어서 C드라이브에 있는 파일을 D드라이브에 옮긴다고 했을때 두 드라이브는 물리적으로 다른 위치에 있습니다. 그야 드라이브 2개를 따로 꽃았을 거잖아요? 그런데 우리가 컴퓨터를 쓸때는 C에 있는 파일을 D에 옮기고자 할때 그냥 간단하게 파일을 드래그 해서 옮김으로써 파일을 옮깁니다. 물리적으로 떨어져 있음에도요.

 

실제로 내부에서는 많은 처리가 이루어지는데 운영체제가 스트림을 이용해 위와 같은 작업을 간편하게 처리해주기 때문에 우리는 드래그-드랍 동작으로 파일을 간편하게 옮길 수 있는것 입니다.

 

파일 입출력 과정에서도 제일 처음에 해야 할게 파일 스트림을 생성하는 것 입니다.

아직은 자세히 설명하지 않았지만 파일 스트림을 생성하고 파일을 여는 함수가 fopen() 함수입니다.

 

운영체제에게 '내가 어떤 파일을 읽거나 파일을 새로 만들어서 뭔가 쓰고 싶은데 그렇게 할 수 있도록 필요한 로직을 좀 처리해줘!' 라고 명령시키는 함수가 fopen() 함수이며, 우리는 이러한 상태를 프로그램과 파일 위치상 소통할 수 있도록 다리가 놓여졌다! 라고 해서 스트림이라고 표현합니다.

 

아까전에 그림으로 표현했던 다리개념이 파일, 프로그램 상에 놓여졌다고 생각해도 좋습니다.

 

이렇게 운영체제가 스트림을 생성해줌으로써 우리는 그 통로로 데이터를 단순히 보내기만 하면 끝입니다. 물론 데이터를 받고 싶으면 데이터를 받는 스트림을 만들어줘! 라고 요청한 다음에 거기서 보내주는 데이터를 받기만 하면 그만입니다. 둘 사이 소통을 위한 전처리들을 우리가 할필요가 없습니다.

 

(내용 출처 - https://jhnyang.tistory.com/196)

 

 

파일 입출력 4 Steps

다음 그림은 파일을 이용한 입출력 과정을 크게 4단계로 나누어 표현한 것입니다.

 

각 스탭별로 자세히 알아보겠습니다.

 

Step 1~2 : 파일 스트림을 생성하고 파일을 연다

 

파일을 입출력할 때는 먼저 파일 스트림을 생성해야 합니다. 파일 스트림을 생성하려면 파일 포인터가 필요합니다. 파일 포인터는 파일에 접근하는데 사용하는 FILE 구조체 포인터를 의미합니다. 즉, 파일 스트림의 실체가 FILE 구조체 포인터 입니다. 

 

이처럼 파일 스트림(=FILE 구조체 포인터)을 생성하고 파일을 여는 함수가 바로 fopen() 함수입니다. * 제일 처음 실습에서 사용해본것

 

위 내용을 그림을 통해 나타내봤습니다.

fopen() 은 운영체제에게 스트림을 준비해달라고 명령하는 함수였습니다.

내가 어떤 파일과 연결하고 싶은지 등의 정보를 담습니다.

 

fopen() 함수가 실행되면 운영체제가 fopen()에 담긴 파일과 통신할 수 있도록 준비하고 그 통신하는데 필요한 정보를 FILE 구조체(파일 스트림)에 담아서 주소로 반환해줍니다. :: 이러한 것을 스트림 정보를 반환했다고 합니다.

 

그러면 그러한 정보를 저장하는 fp1 변수의 경우 FILE * => FILE 구조체 포인터의 형식으로 자료형이 설정되었기 때문에 운영체제가 반환간 파일 구조체의 주소를 가리키게 됩니다.

 

스트림 정보를 담은 포인터가 하나 생겼으므로 (fp1) 이를 이용하면 원하는 파일에 접근할 수 있습니다.

 

* 반환하는 FILE 구조체 멤버 변수에 직접적으로 접근할 일은 없기 때문에 FILE 구조체가 어떻게 정의되어 있는지는 알 필요가 없습니다.

따라서 우리는 단순히 FILE 구조체(또는 구조체 포인터) 를 단순히 파일 스트림의 실체라고 이해하면 됩니다.

 

 

Step3 파일 입출력을 수행한다

 

파일 스트림을 생성하고, 파일을 연 후에는 여러 입출력 함수를 이용해서 입출력 작업이 가능합니다. 파일 입출력에 사용하는 함수는 뒤에서 설명합니다.

 

Step4 파일을 닫는다

 

파일 입출력이 끝난 후에는 파일을 닫아야 하는데 이때 사용되는 함수는 fclose() 입니다.

fclose() 함수는 스트림을 닫는 역할을 합니다.

 

정리해서 파일 스트림 생성, 파일 열기를 fopen() 함수로 처리 => 파일 입출력을 수행 => fclose() 함수로 파일 닫기가

파일 입출력 과정입니다.

 

또한 fopen() 으로 파일을 열어주셨으면 처리가 끝난 후 반드시 fclose() 로 닫아주셔야 합니다.

fopen() - fclose()는 한쌍으로 따라다닌다고 보시면 됩니다.

 

이유가 궁금하신 분들은 아래 링크 참고

 

https://blog.naver.com/kwy1052aa/221768803143

 

C 언어 프로그램 fclose() 및 파일 개방 모드

지난 글에서 C 언어 프로그램에서 파일을 대상으로 한 입출력을 위해서 fopen() 함수를 이용해서 파일과 ...

blog.naver.com

 

다음편에서 계속됩니다..

 

COMMENT WRITE