📚파일 입출력

파일은 디스크에 저장된 일련의 바이트로 C 프로그램은 운영체제를 통해서 파일을 읽거나 쓰게 된다. 파일은 텍스트 파일과 2진 파일로 구분된다. 파일 입출력은 파일에 대한 입력과 출력을 말한다. 파일 입력은 디스크상의 특정 위치에 저장되어 있는 자료를 읽어 기억공간에 수록하는 절차이고, 파일 출력은 기억공간에 있는 자료를 디스크상의 특정 위치에 저장하는 절차이다.

모든 파일 입출력 함수는 파일이 어디에 있는지 가리키는 파일 포인터를 사용한다. 또한 디스크에 저장된 자료를 기억공간으로 읽어 들이거나, 기억공간에서 처리된 자료를 디스크에 저장할때 기억공간과 디스크 사이에 존재하는 버퍼라는 임시 기억공간을 사용한다. 컴퓨터 내부의 처리는 속도가 매우 빠른 반면 디스크 드라이버는 처리시간이 많이 소요된다. 따라서 디스크에 저장된 자료를 읽어올 때 버퍼의 크기만큼 일정량의 자료를 버퍼에 채우고 CPU가 버퍼에 들어있는 자료를 한꺼번에 처리하는 방식을 쓴다. 반대로 파일 출력은 처리된 자료를 버퍼에 넣고 버퍼가 가득 차면 한꺼번에 디스크로 출력하게 된다.



📚파일 포인터를 이용한 파일 입출력

프로그램과 입출력 장치 사이에 입출력이 이뤄지기 위해 논리적인 통로가 있어야 한다. 이런 통로를 스트림이라고 하는데 프로그램과 키보드 사이에 입력 스트림이 있어 표준입력함수를 이용해 자료 입력이 가능하게 한다. 또한 프로그램과 모니터 사이에 출력 스트림이 있어 표준출력함수를 이용해 자료 출력이 가능하게 한다. 표준 입출력 스트림은 운영체제에 의해 만들어지는데 프로그램 실행시 자동으로 생성되고 프로그램 종료 시 자동으로 소멸된다.

파일 입출력도 자료의 입출력을 위해 스트림이 필요한데 표준 입출력 장치에서의 표준 스트림은 자동을 생성되고 소멸되는 반면, 파일 입출력을 위한 스트림은 프로그램을 통해 생성하고 소멸 시켜 주어야 한다.


📄파일 입출력 수행 과정

  1. 파일 열기
  2. 입출력 수행
  3. 파일 닫기

1번의 파일 열기 과정은 파일 입출력 스트림을 생성한다는 의미로 볼 수 있다. fopen() 함수로 스트림을 생성하고 파일을 연다. 3번의 파일 닫기 과정은 fclose() 함수로 스트림을 소멸시키고 파일을 닫는다. 파일과 프로그램의 통로 역할을 하는 스트림은 파일 포인터이다. 따라서 파일 포인터를 이용하여 파일 입출력이 이뤄지게 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// sample.txt. 파일을 쓰기 모드로 열고(파일이 없으면 생성)
// 'A'에서 'Z'까지 순서대로 출력(저장)하고 파일을 닫는 프로그램

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

void main()
{
	FILE* fp;   // 파일 포인터 선언
	char c;

  // sample.txt 파일 열기/생성
	fp = fopen("sample.txt", "w");  

	for (c = 'A'; c <= 'Z'; ++c)
	{
		fputc(c, fp);   // 자료 출력
	}

	fclose(fp);   // 파일 닫기
}


파일 입출력 관련 함수는 <stdio.h>에 원형이 선언되어 있다.

함수 기능
fopen(“파일명”, “모드”) 파일을 지정한 모드로 열기
fclose() 파일 닫기
fgetc(), getc() 파일로부터 한 문자 읽기
fputc(), putc() 파일에 한 문자 쓰기
fgets() 파일로부터 문자열 읽기
fputs() 파일에 문자열 쓰기
fscanf(fp) 파일로부터 정해진 형식에 따라 읽기
fprintf() 파일에 정해진 형식에 따라 쓰기
fread() 파일로부터 정해진 크기의 자료를 정해진 개수만큼 읽기
fwrite() 파일에 정해진 크기의 자료를 정해진 개수만큼 쓰기
fseek() 파일에서 입출력 위치 이동
feof() 파일의 끝 판별
ferror() 파일의 입출력 시 에러 발생 유무 조사


파일은 편성하는 방법에 따라 순차파일과 램덤파일로 나눌 수 있다. 순차파일은 자료를 처음부터 차례대로 읽고 기록하는 파일이고, 랜덤 파일은 파일의 임의의 위치에서 자료를 읽고 기록하는 파일이다.


📄 파일 포인터 선언과 파일 열기

  • 파일 포인터 선언

파일 입출력을 위해 파일 포인터를 선언해야 한다. 파일 포인터는 파일과 프로그램을 연결해주는 통로 즉, 스트림이 된다.

1
FILE* 변수명;


FILE형은 구조체로 되어 있고 <stdio.h>에 정의되어 있다. FILE형 구조체 변수는 파일에 대한 여러 가지 정보를 지닌 변수로, 자료를 입출력할 때와 파일 내의 위치 정보 그리고 파일의 끝을 확인하는데 사용된다. 또한 FILE형으로 선언된 파일 포인터 변수는 버퍼의 어떤 부분을 가리키게 된다. 파일 포인터 변수는 동시에 여러개 선언될 수 있고 각각의 버퍼를 갖게 된다.


  • 파일 열기

파일 열기는 프로그램과 파일 사이에 데이터가 입출력할 수 있도록 통로를 만들어 주는 것이다. fopen() 함수를 사용하고 정상적으로 입출력이 가능하면 파일의 파일 포인터 시작 주소값을 리턴한다. 파일이 열리지 않을 때는 null이라는 에러값을 리턴한다.

1
fopen("파일명", "사용 모드");


fopen() 함수에서 파일명은 드라이브나 경로를 포함할 수 있다.

1
2
fopen("c:\sample.txt", "사용 모드");
fopen("c:\KNOU\sample.txt", "사용 모드");


fopen() 함수의 사용 모드는 파일의 사용 용도를 결정한다. 사용 모드는 자료 입출력 방식을 의미하고 C 언어에서는 텍스트 모드와 2진 모드를 정의하고 있다. 텍스트 모드는 파일로 자료를 입출력할 때 변환이 일어나지만 2진 모드는 파일로 자료를 입출력할 때 아무 변환이 일어나지 않는다. fopen() 함수의 사용 모드는 아래 표와 같다.

사용 모드 의미 파일 있을 경우 파일 없을 경우
“r” 파일 읽기만 기능 정상 처리 null값 반환
“r+” 파일 읽기, 쓰기, 추가 기능 정상 처리 null값 반환
“w” 파일 쓰기와 추가 기능 이전 내용 덮어씀 새로운 파일 생성
“w+” 파일 읽기, 쓰기, 추가 기능 이전 내용 삭제 새로운 파일 생성
“a” 파일 추가만 기능 이전 내용 뒤에 추가 새로운 파일 생성
“a+” 파일 읽기와 추가만 기능 이전 내용 뒤에 추가 새로운 파일 생성

위의 사용 모드는 텍스트 파일 사용 모드이고 텍스트 파일 사용 모드에 문자 t를 첨부하기도 한다. 2진 파일 사용 모드는 문자 b를 첨부하면 된다.

1
2
3
4
5
fopen("파일명", "wt");    // 텍스트 모드 출력 개방
fopen("파일명", "rt");    // 텍스트 모드 입력 개방

fopen("파일명", "wb");    // 2진 모드 출력 개방
fopen("파일명", "rb");    // 2진 모드 입력 개방


fopen() 함수는 보통 단독으로 쓰이지 않는다. 개방이 불가능하여 null값이 반환될 경우를 고려해야 하기 때문이다. 따라서 개방이 안되어 null값이 반환될 때 개방이 불가능하다는 메시지를 출력하도록 한다.

1
2
3
4
5
if(fp = fopen("파일명", "사용 모드") == NULL)
{
  fputs("파일을 열 수 없습니다!");
  exit(1);
}

exit() 함수는 괄호 안의 값이 0이면 프로그램이 정상적으로 종료되었다는 의미고, 괄호 안의 값이 0이 아닌 값이면 비정상적인 프로그램의 종료를 의미한다.


아래는 2개의 파일 포인터를 선언하고, 쓰기용과 읽기용 파일을 개방하는 코드이다.

1
2
3
4
FILE *fp1, *fp2;

fp1 = fopen("d:\sample1.txt", "w");
fp2 = fopen("c:\sample2.txt", "r");


  • 파일 닫기

파일 닫기는 개방된 통로와 버퍼를 원래 상태로 환원시킨다. 개방한 파일이 쓰기 모드인 경우 파일의 끝에 끝을 나타내는 EOF(End of File)신호를 달아서 완전한 파일로 만들어 준다.

1
fclose(파일 포인터 변수)
1
2
3
4
5
6
7
FILE *fp1, *fp2;

fp1 = fopen("d:\sample1.txt", "w");
fp2 = fopen("c:\sample2.txt", "r");

fclose(fp1);
fclose(fp2);



Leave a comment