08 파일 처리 함수
1절 파일 입∙출력
l 데이터를 미리 저장한 파일로 입력 받고 결과를 파일로 저장
l <stdio.h>이 파일 입∙출력 함수 제공
1. 파일
n 파일 : 디스크나 자기 테이프 등과 같이 보조기억장치에 파일명으로 저장된 물리적 데이터 집합체
n 프로그램 파일 / 데이터 파일로 나뉨
1) 프로그램과 데이터
u 프로그램 : 특정 문제를 해결하기 위해 CPU가 실행할 명령을 모아둔 파일
u 데이터 : 프로그램 파일이 실행되면서 처리할 데이터 or 프로그램 실행 동안 처리한 결과 모아둔 파일
2) 파일에 저장된 데이터 형식에 따른 분류
(1) 텍스트 파일 : 파일 내용이 사람이 알고 있는 문자로 표시
사용자가 키보드로 직접 입력해서 만든 프로그램 소스파일/ 메모장에서 작성한 파일
(2) 이진 파일 : 컴퓨터의 특정 프로그램에 의해서만 읽을 수 있는 파일 (exe 파일, 음악/이미지 파일)
3) 파일은 접근 방식에 따른 분류
(1) 순차(sequential) 파일
o 데이터를 처음부터 순차적으로 읽거나 씀
o 이미 읽은 데이터를 다시 읽으려면 파일을 닫은 다음 다시 열어야 됨
o 파일의 맨 처음부터 읽어서 원하는 위치까지 이동하여 데이터를 읽어야 함
(2) 랜덤(random) 파일
o 파일의 어느 위치든 곧바로 이동하여 읽고 쓰기 가능
o 어떤 파일이든 순처적으로 접근할 수도 있고 임의적으로 접근할 수 도 있음
2. 파일 처리 과정
n 파일 포인터 선언 -> 파일 열기 -> 파일 읽기 -> 파일 닫기
1) 파일 포인터 선언
u FILE 구조체형 포인터 필요 -> ‘파일 포인터’ 라고 함
u FILE : 헤더파일 stdio.h에 정의된 구조체 자료형. 파일 읽/쓰에 필요한 정보 저장하는 구조체
u 작업 대상인 파일의 정보를 전달하는 인수로 사용
u 파일 포인터가 할당되어 있는 파일에 대해서만 읽/쓰 가능
u FILE *파일 포인터 변수명
FILE *fp;
2) 파일 열기 : fopen( )함수
u 파일을 open하는 작업 -> FILE 구조체를 파일 포인터와 연결
u 운영체제에게 파일 사용하겠다고 요청하는 것
u 파일 포인터 변수명 = fopen(“파일명”, ”모드”);
o fopen 함수 : “파일명”의 파일을 “모드”에 맞게 open한 후 파일 정보가 든 FILE구조체의 시작주소 반환
o fopen함수가 반환한 FILE구조체 시작주소를 파일 포인터에 연결해 포인터가 참조하게 함
o 파일 열기 실패 -> NULL 반환
o 모드 : 파일 읽기 (r), 쓰기 (w) 등 지정하고 참조모드 형태모드 조합 !
(1) 파일 참조 모드
(2) 파일 형태 모드
o 파일명만 명시하면 현재 작업중인 프로젝트 폴더 안에서 파일 찾음
o 절대 경로로 명시하면 절대경로에서 파일 찾음
o FILE *fp = fopen(:data.txt”, “w”);
(3) NULL문자 반환
o 파일 열기 실패하면 NULL문자 반환 -> 파일 관련 어떠한 작업도 더 이상 처리 안됨
o 보통 프로그램 강제로 종료하도록 exit(1); 을 함
o FILE *fp = fopen(“data.txt”, “r”);
if(fp==NULL)
exit(1);
3) 파일 입∙출력 함수
4) 파일 닫기 : fclose( )함수
u 파일 읽/쓰기 끝나면 프로그램 종료 전 반드시 열린 파일 닫아야 함
u fclose(파일 포인터 변수명);
o 파일 포인터명과 연결된 파일이 닫히고 파일 포인터와의 연결이 해제됨
o 연결 해제된 파일 포인터는 다음 파일 다시 연결해 사용 가능
o 파일 닫기 성공하면 0 반환 / 실패하면 -1 반환 (EOF상수 : END OF FILE)
3. 형식을 지정한 파일 입∙출력
n 형식에 맞추어 읽고 쓰는 fsanf() / fprintf()! 일반 파일 뿐 아니라 장치 파일까지 입∙출력 할 수 있음
n 기존 파일 내용 프로그램서 읽으려면 파일에 저장된 데이터 형식 순서 알고 그에 맞게 읽어야 함
1) 형식을 지정한 파일 출력 : fprintf( )함수
u fprintf(파일 포인터 변수, “변환명세 포함한 형식 문자열”, 변수명);
o 변수에 저장된 값을 형식문자열에 맞게 변환하여 파일포인터 연결된 파일에 기록
o
u 파일 포인터 변수명을 stdout으로 지정하면 모니터로 출력됨
int age = 2;
fprintf(fp, “나이 : %d세”. age);
fprintf(stdout, “나이 : %d세”. age);
u 변환 명세 형식 문자열에 빈칸이나 엔터키를 입력하여 데이터 간 구분 필요
2) 형식을 지정한 파일 입력 : fscanf( )함수
u fscanf(파일 포인터 변수, “변환 명세”, &변수명)
파일 포인터에 연결된 파일에서 변환명세에 맞게 데이터를 한 개 읽어 변수명에 저장
파일 포인터 변수명을 stdin으로 지정하면 키보드에서 입력 받음
읽기에 실패하거나 파일의 끝에 도달하면 EOF 반환(성공 0 /실패 -1)
u 변환 명세 끝에 빈칸 / \n X, 일반 문자를 변환명세에 포함 X
u FILE *fp=fopen(“read.txt”);
fscanf(fp, “%d”, &age); ---> 이러면 안됨 fscanf(fp, “키 : %5d ”, &height);
변환명세에 공백, 일반 문자 X 필드폭 사용 비추
3) 파일 추가
u 파일 참조에 추가모드로 파일을 열어 파일의 끝에 자료 추가
u 실행결과와 같은 파일에 새 실행결과를 저장하고 싶을 때 사용
u open할 파일 없으면 지정한 파일 이름으로 파일 새로 생성
u fp = fopen(“text.txt”, “a”);
4) 파일의 끝 확인
(1) feof( ) 함수 활용하기
o 책갈피 역할!
o 읽기/쓰기 시작할 위치를 가리키는 파일 위치 지시자(FILE 구조체의 포인터 멤버)
- 파일 위치 지시자 file position indicator -> FPI로 써야지 귀찮아
o 파일 입∙출력 함수 호출 시 인수로 지정한 파일 포인터가 가리키는 file구조체의 FPI가 가리키는 곳부터 읽기/쓰기 진행
- 파일 닫으면 파일 마지막 데이터 다음에 시스템에 의해 파일 끝 표시하는 특별한 문자 자동으로 저장됨(시스템만 인식 가능 ^Z(ctrl+Z)로 표현)
- FPI가 이 특별 문자 가리킬 때 읽기 시도 -> 더 이상 읽을 데이터 없으므로 FPI는 파일의 처음 위치로 수정됨
- FILE 구조체의 특정 플래그가 파일 끝 지났음을 표시 (1로 세팅됨)
- 플래그가 1로 세팅된 경우면 파일에서 더 읽을 자료가 없음을 의미 -> 읽기를 그만둠
o feof(파일 포인터 변수명)
- 파일 포인터 변수명이 가리키는 FILE구조체에서 파일 끝 지났음을 알려주는 플래그를 참조하여 반환 값을 반환
o 파일 끝(문자)를 지나갔을 때 0이 아닌 값(참 = 1) 반환 (도달했을 때가 아님)
- 프로그램 실행을 통해 만들어지는 파일이 상황에 따라 빈 파일 만들어 지기도 함
- 데이터 전혀 없는 빈 파일 끝에는 끝 나타내는 특수문자만 포함
- 빈 파일 열고 feof( )호출하면 0 나오는데, FPI 맨 끝을 가리키기만 함
-> 끝 문자를 지나가지 않았기 때문
o feof( ) 함수 사용의 잘못된 예
1 2 3 4 5 |
while (!feof(fp)) { fscanf(fp, “%d”, &age); printf(“%2d세 \n, age); } 라고 했을 때 |
① fp 참조 파일에 아무 데이터 없을 때 - 1 ~ 5행 : FPI는 특수문자 가리키므로 !feof()는 참 (!0) - 3행 : 조건이 참이라 실행 되지만 안에 읽을 정수 없어서 age에 값 저장 안됨 - 4행 : age 초기화 안되어 쓰레기 값 출력
|
|
파일이 20 21 22
이렇다면 |
② fp 참조 파일에 3명 나이 저장되어 있을 때 데이터가 개행 문자로 나뉘어져 있다면 - 1 ~ 5행 : FPI는 파일의 처음을 가리킴 FPI가 가리키는 곳에서 데이터를 읽고 age에 저장하는 것을 반복하나 파일의 데이터 뒤 개행 문자가 있으므로, 데이터를 읽은 후 개행 문자를 가리키게 됨 처음 20 읽고 저장 -> FPI는 그 뒤 개행 문자 가리킴 개행 문자 무시하고 그 뒤 21 읽고 저장 -> FPI는 그 뒤 개행 문자 가리킴 개행 문자 무시하고 그 뒤 22 읽고 저장 -> FPI는 그 뒤 개행 문자 가리킴 개행 문자를 가리키므로 데이터는 끝났으나 while 조건문 !feof(fp)가 아직 참 while문을 한 번 더 반복 함 - 3행 : FPI가 읽은 개행 문자는 읽은 후 무시하고 정수 읽으려 하지만 파일 끝 문자 지나게 되고 읽을 정보 없어서 EOF 반환 - 4행 : 이 전에 age 저장되었던 마지막 값을 출력. 같은 나이가 또 출력됨 |
||
(2) fscanf( ) 함수의 반환 값을 활용
o fscanf( ) 함수는 파일 끝에 도달하거나 오류가 나면 EOF 반환
o 파일 읽기 시도 한 후 fscanf( ) 함수 반환 값 확인 해 읽기 성공여부 확인 가능
o 선호하는 방법!
o while (fscanf(fp, “%d”, &age) !=EOF)
printf(“%2d \n, age);
4. 문자 단위 파일 입∙출력
n 파일에 저장된 모든 데이터는 연속된 바이트로 구성, 어떠한 파일도 바이트 단위로 쓰고 읽기 가능
1) 문자 단위로 파일에 쓰기 : fputc( )함수
u 문자 단위로 씀
u fputc(문자, 파일 포인터 변수명);
문자를 파일 포인터 변수가 가리키는 파일에 씀
fputc(‘a’, fp);
u fputc(정수, 파일 포인터 변수명);
ASCII 코드 값이 정수에 해당하는 문자 한 개를 파일 포인터 변수가 가리키는 파일에 씀
fputc(67, fp);
2) 문자 단위로 파일 읽기 : fgetc( )함수
u 파일에서 문자 한 개를 읽어 반환
u fgetc(파일 포인터 변수명);
o 반환형을 읽은 문자의 ASCII코드 값이 반환됨 -> int형
o 읽기 오류 발생하거나 파일 끝에 도달하면 -1에 해당하는 EOF상수 반환
o char ch;
FILE *fp = fopen(“data.txt”, “r”);
ch = fgetc(fp);
5. 문자열 단위 파일 입∙출력
n 텍스트 파일에 저장된 내용을 문자열 단위로 입∙출력 함수 fputs( ), fgets( )
n puts( ), gets( )와 개행 문자 다루는 데 있어 차이가 있음 ! 주의 필요
1) 문자열 단위 출력 : fputs( )함수
u 문자열 단위로 파일 쓰기
u 자동으로 개행 문자 넣지 않음
u fputs(문자열 시작 주소, 파일 포인터 변수명);
o 문자열 시작 주소에 저장된 문자열을 파일 포인터에 연결된 파일에 씀
o 문자열의 끝을 나타내는 널문자 파일에 쓰지 않음
o 개행 문자 자동으로 추가 X
o 출력 성공하면 출력한 바이트 수 반환, 실패하면 EOF 반환
u fputs(“문자열 단위 출력 \n”, fp); 처럼 같이 출력할 문자열에 포함된 개행 문자는 출력
2) 문자열 단위 출력 : fgets( )함수
u 파일에 쓰여진 개행 문자까지 문자열에 포함시킴
u 한 번에 읽을 수 있는 문자열 길이 정해져 있어 행이 길면 행 전체를 못 읽을 수도 있음
o 한 행 단위로 읽고 싶으면 최대 입력 문자 수를 충분히 크게 지정
u fgets(문자열 저장 주소, 최대 입력 문자 수, 파일 포인터 변수명)
o 파일 포인터에 연결된 파일에서 (최대 입력 문자수 – 1)개의 문자 읽은 후 뒤에 널문자(\0) 합친 문자열을 지정한 문자열 저장 주소부터 저장
o 최대 입력한 문자 개수만큼 읽지 않았지만 중간에 개행 문자(\n)읽으면 읽기 쥥단하고 뒤에 널문자 합친 문자열 저장 -> 개행문자도 문자열에 포함
o 파일 끝에 도달하거나 오류 발생시 NULL포인터 반환
2절 이진 파일 입∙출력
l 텍스트 파일은 모든 데이터가 문자열로 변환되어 기록됨
n fprintf( ) : 정수를 문자로 변환하여 파일에 기록
n fscanf( ) : 파일에서 문자로 된 숫자를 읽어 정수로 변환하여 변수에 저장
l 이진 파일은 수치 데이터가 문자로 변환되지 않고 곧바로 수치로 저장됨
n 수치를 읽을 때 한 개의 수치로 바로 읽음 -> 수치와 문자열 간 변환 과정 없음
n 읽고 쓰기 빠름 / 저장 공간 적게 차지(정수의 경우 언제나 4바이트 이므로)
n 컴퓨터 기종이 다를 경우 수치 표현 방식이 다를 수 있음 -> 내용 달라질 수 있음
l 이진 파일은 행으로 분리되지 않음
n 행의 끝 표시할 필요 없음
n 널 문자, 개행 문자 같은 글자들도 특별한 의미 없이 데이터로 취급
n 눈으로 내용을 확인하기 어려우므로 특정 프로그램 사용해야 함
l FILE *fp = fopen(“파일명”, “wb/rb/ab”);
n 형태 모드 주의!
u wb : 이진 파일 쓰기 전용
u rb : 이진 파일 읽기 전용
u ab : 이진 파일 추가 전용
1. 이진 파일에 쓰기 : fwirte( ) 함수
n 블록 (block 바이트 단위의 연속된 데이터 집합)으로 파일 씀
u 일정한 크기의 데이터를 통째로 읽거나 쓸 수 있음
n fwrite( )함수 이용해 만들어진 파일에서 데이터 읽어올 때 블록 크기에 주의해서 정확한 크기의 블록단위로 읽어와야 함
n fwrite(데이터 시작 주소, 블록 크기, 블록 개수, 파일 포인터 변수명);
u 데이터 시작 주소부터 저장된 (블록 크기 * 블록 개수) 바이트의 데이터를 파일 포인터 변수에 연결된 이진 파일에 쓴 후 파일에 쓴 블록 개수 반환
u 블록 크기 : 바이트 단위 / 블록 개수 : 정수
u 이진 파일에 쓰는 데이터 형은 달라도 됨. 이진 파일에서 읽어올 때 데이터 기록한 순서와 정확이 일치하도록 읽어와야 함
int age[10] = {20,21,22,23,24,25,26,27,28,29} fwrite(age, sizeof(int), 10, fp); |
double height = 175.5; fwrite(height, sizeof(double), 1, fp); |
2. 이진 파일에 읽기 : fread( ) 함수
n 이진 파일에서 데이터 블록 읽어 오는 함수
n fread (데이터 저장 시작 주소, 블록 크기, 블록 개수, 파일 포인터 변수명);
u 파일 포인터 변수에 연결된 파일에서 (블록 크기 * 블록 개수) 바이트의 데이터를 읽어서 시작 주소에 저장 후 읽은 블록 개수 반환
u 블록 크기 : 바이트 단위 / 블록 개수 : 정수
u 데이터 저장 시작 주소에 해당하는 기억장소는 (블록 크기 * 블록 개수) 바이트의 데이터 저장하기에 충분한 기억장소여야 함
n int age[10];
FILE *8fp = fopen(“data.bin”, “rb”);
fread(age, sizeof(int), 10, fp);
3절 파일의 임의 접근
l 임의 접근 : 파일 읽기/ 쓰기를 순서대로 X -> 임의의 위치에서 바로 읽기/쓰기 할 수 있는 접근 방식
l 파일 위치 지시자 조작하는 함수로 읽기 쓰기 시작 위치 조정 -> 커서
1. 파일 위치 지시자 이동하기 : fseek( ) 함수
n fseek(파일 포인터 변수명, 오프셋, 기준점)
u 파일 위치 지시자가 기준점으로부터 오프셋만큼 떨어진 곳을 가리키게 함
u 읽기 쓰기 시작 위치 = (기준점 + 오프셋) 바이트 위치
u 이동에 성공하면 0 반환, 실패하면 0이 아닌 값 반환
n 기준점
u SEEK_SET : 0. 파일의 시작 지점 의미
u SEEK_CUR : 1. 파일의 현재 지점 의미
u SEEK_END : 2. 파일의 끝 지점 의미
n 오프셋 : long형 정수. 기준점 이전이면 음수 / 기준점 이후면 양수 사용
n fseek(fp, 100, SEEK_SET);
fseek(fp, 100, SEEK_CUR);
fseek(fp, -100, SEEK_END);
2. rewind( ) 함수
n rewind(포인터 변수명)
파일 포인터에 연결된 파일의 다음 읽기/쓰기 위치를 파일의 시작 지점으로 이동
= fseek(fp, 0, SEEK_SET);
3. ftell( ) 함수
n 현재 파일의 읽기/ 쓰기 위치 알려줌 (파일 위치 지시자(FPI)가 가리키는 곳을 알려줌)
n 파일의 시작 위치가 상대적으로 0
현재 FPI가 가리키는 곳이 파일의 시작위치로부터 몇 바이트 떨어져 있는지 반환
n ftell(파일 포인터 변수명)
position = ftell(fp);
'[시험] 독학사 2020 전공기초' 카테고리의 다른 글
[독학사][컴퓨터 시스템 구조] 08 보조기억장치 (0) | 2020.05.01 |
---|---|
[독학사][컴퓨터 시스템 구조] 01 컴퓨터 시스템 개요 (0) | 2020.05.01 |
[독학사][C프로그래밍] 07 구조체와 공용체 (0) | 2020.04.28 |
[독학사][C프로그래밍] 06 배열과 포인터 (0) | 2020.04.28 |
[독학사][C프로그래밍] 05 함수와 기억클래스 (0) | 2020.04.28 |