9장 파일 입출력
목차 1. 파일 입.출력 2. 시스템 입.출력 함수 1.1 파일 포인터 1.2 파일 open 1.3 파일 유형별 입.출력 함수 1.4 레코드 포인터 2. 시스템 입.출력 함수
1. 파일 입.출력 스트림(Stream) 스트림을 사용하는 이유 바이트의 흐름을 나타내는 논리적인 장치(혹은 단위) 입출력장치(키보드,모니터,파일,네트워크,DB등)와 Application(프로그램) 간의 데이터를 주고받는 인터페이스(interface)역할 스트림을 사용하는 이유 모든 입출력 장치에 공통된 인터페이스를 제공하기 위해 모니터 키보드 Application (프로그램) 파일 네트워크
1. 파일 입.출력 표준 입.출력 스트림 키보드,모니터로 데이터 입출력을 위한 인터페이스 키보드로 데이터를 입력 표준 입력 스트림 모니터로 데이터를 출력 표준 출력 스트림 키보드 프로그램 모니터 표준 입력 스트림 표준 출력 스트림
1. 파일 입.출력 표준 입출력 스트림 표준 입출력 스트림의 생성과 소멸 생성 : 프로그램 시작 시 소멸 : 프로그램 종료 시 용도 장치 stdin 표준 입력을 담당 키보드 stdout 표준 출력을 담당 모니터 stderr 표준 에러를 담당
1. 파일 입.출력 표준 입출력 함수의 종류(헤더파일 : stdio.h) 함수의 원형 기능 스트림 int getchar (void); 키보드로 부터 한 문자를 입력 받는다. stdin int putchar (int c); 모니터에 한 문자를 출력한다. stdout char* gets (char *s); 키보드로 부터 문자열을 입력 받는다. int puts (char* str); 모니터에 문자열을 출력한다. int scanf (const char* format, …); 키보드로 부터 데이터를 서식에 맞춰 출력한다. int printf (const char* format, …); 모니터에 데이터를
getchar( ) 함수 putchar( ) 함수 EOF(End Of File) 문자를 입력하는 함수 문자를 출력하는 함수 파일의 끝을 의미 stdio.h 에 -1로 매크로 상수 정의 [ctr+z]를 입력하면 EOF로 인식
예제. #include<stdio.h> int main(void) { char ch=0; while( ch != EOF) // EOF == -1 ch=getchar(); putchar(ch); }; return 0; }
1. 파일 입.출력 표준 입출력 스트림 파일 입출력 스트림 언제든지 표준 입출력 함수 대신 파일 입출력 함수를 이용해서 표준 입출력을 처리할 수 있다.
1. 파일 입.출력 파일 입출력의 필요성 ‘실행 중에 데이터가 생성되면 데이터는 메모리에 보관 된다.’ 문제점 : 프로그램이 종료되면 사라짐 데이터를 프로그램이 종료된 후에도 계속해서 사용하려면? 파일에 저장 ‘중요한 데이터를 파일에 저장한다.’ ‘필요할 때 파일을 읽어 데이터를 사용한다.’
1. 파일 입.출력 파일 입출력의 기본 틀
1. 파일 입.출력 파일의 입출력 절차 파일 열기 실제 파일입출력 작업 시행 모든 입출력이 끝나면 파일을 닫는다. 먼저 스트림을 생성한 다음에 입출력을 수행 fopen 함수로 파일을 열면 파일 포인터가 리턴된다. 파일에 접근하려면 항상 파일 포인터가 필요하다. 실제 파일입출력 작업 시행 텍스트 파일 입출력 : fgetc, fputc, fgets, fputs, fscanf, fprintf 바이너리 파일 입출력 : fread, fwrite 모든 입출력이 끝나면 파일을 닫는다. 파일을 닫을 때 fclose 함수 사용
1.1 파일 포인터 파일 포인터(파일 스트림) 선언 형식: FILE * 파일포인터이름; 예) FILE* fp; 파일 구조체
1.2 파일 Open 파일 스트림 생성/삭제 함수 fopen(filename, mode) 첫번째 인수 open할 파일이름 파일의 경로와 이름을 동시에 표현 : 절대경로, 상대경로 두번째 인수 파일(읽기,쓰기, 텍스트, 바이너리등) 모드 설정 파일의 접근 모드와 파일의 입출력모드 표현 리턴 값 생성된 파일 스트림(파일 포인터) 함수의 원형 설명 #include <stdio.h> FILE* fopen (const char* filename, const char* mode); 파일 스트림을 생성하고 파일을 연다. 호출 실패의 경우: NULL 반환 int fclose (FILE* stream); 파일을 닫는다. 호출 실패의 경우: EOF 반환
1.2 파일 Open 파일의 접근 모드 (r, w, a, r+, w+, a+) r w a r+ w+ a+ 모드 설명 읽기 전용으로 파일을 연다. 파일이 없거나 찾을 수 없는 경우에 호출 실패 w 쓰기 전용으로 파일을 연다. 지정한 파일명이 있는 경우: 파일 내용을 모두 지우고 새로 만든다. 지정한 파일명이 없는 경우: 새로운 파일을 생성 한다. a 추가 쓰기 전용으로 파일을 열다. 지정한 파일이 있으면 파일의 끝에서부터 내용을 추가합니다. r+ 파일을 읽고 쓰기 위해 연다. 지정한 파일이 있는 경우: 기존의 내용을 덮어쓴다. 지정한 파일이 없는 경우: 새로운 파일을 생성하지 않는다(파일열기오류). w+ 지정한 파일이 있는 경우: 파일의 내용을 모두 지우고 새 파일을 만든다. 지정한 파일이 없는 경우: 새로운 파일을 생성 한다. a+ 파일을 읽고 추가 쓰기 위해 연다. 파일이 없으면 새로 생성하고, 파일의 어떤 위치도 읽을 수 있지만 쓰기는 파일의 맨끝에만 할 수 있다. 나머지 기능은 r+와 같다.
1.2 파일 Open 파일 입출력 모드 text 모드 binary 모드 모드 설명 t 텍스트 파일 모드 b 바이너리 파일 모드
1.2 파일 Open 파일의 유형 텍스트 파일(Text File) 바이너리 파일(Binary File) 데이터 내용을 확인할 수 있는 문자들을 저장해놓은 파일 문자열과 같은 텍스트 기반의 데이터 파일 예) *.txt, *c, *.doc 바이너리 파일(Binary File) 일반 문서 편집기에서 내용을 확인 할 수 없음 이진 형식으로 인코딩된 데이터 파일 바이너리 파일을 텍스트 모드로 열면 글자가 깨지는 현상이 발생 예) *.obj, .exe, *.lib
1.2 파일 Open r : 읽기 (read) w: 쓰기 (write) a: 추가 (append) 파일 접근 모드 텍스트/바이너리 모드 파일 오픈 모드 r : 읽기 (read) w: 쓰기 (write) a: 추가 (append) t : 텍스트 파일 모드(text file mode) b: 바이너리 파일 모드 (binary file mode)
/* case 1 */ FILE* stream; stream=fopen("d:\\project\\data.txt", "rt"); /* case 2 */ FILE* stream stream=fopen("data.txt", “wt"); /* case 3 */ stream=fopen(“.\\data.txt", “r"); /* case 4 */ stream=fopen("d:\\project\\data.txt", “w"); /* case 5 */ stream=fopen(“..\\data.txt", “ab"); 텍스트 모드의 경우 ‘t’ 생략 가능
파일 Close 파일 입출력이 끝나면 fclose 함수를 호출해서 반 드시 파일을 닫아야 한다. fclose 함수의 원형 stream : 파일 포인터 리턴 값 파일 닫기 성공 : 0 리턴 파일 닫기 실패 : EOF(-1) 리턴
예제. #include<stdio.h> int main(void) { FILE* fp; // 파일 스트림 생성을 위한 FILE 포인터 선언 int file_state; // 파일의 종료를 위한 상태 체크 변수 선언 // 파일 스트림 생성과 파일 열기 fp = fopen("data1.txt", "r+"); if (fp == NULL) // 파일이 없는 경우 printf("파일 열기 에러\n"); else puts("파일 열기 성공\n"); // 파일 닫기(파일 스트림 소멸) if (fp == NULL) puts("파일이 열려있지 않습니다."); else { file_state = fclose(fp); if (file_state == EOF) puts("파일 닫기 에러"); puts(“파일 닫기 성공"); file_state = fclose(fp); // 파일 닫기 재시도 } 예제.
1.3 파일 유형별 입.출력 함수 표준 입출력 함수와 표준 파일 입출력 함수 stdin stdout stdin stdout 표준파일 입출력 함수 기능 int getchar (void); int fgetc (FILE* stream); 문자 단위 입력 int putchar (int c); int fputc (int c, FILE* stream); 출력 char* gets (char *s); char* fgets (char *s, int n, FILE* stream); 문자열 단위 int puts (char* str); int fputs (const char* s, FILE* stream); int scanf (const char* format, …); int fscanf (FILE* stream, const char* format, …); 자료형에 맞춘 int printf (const char* format, …); int fprintf (FILE* stream, const char* format, …); stdin stdout stdin stdout stdin stdout
1.3 파일 유형별 입.출력 함수 한 문자 입출력 함수 키보드로부터 한 문자 입력 파일로부터 한 문자 입력 fgetc(stdin) = getc(stdin) = getchar( ) 파일로부터 한 문자 입력 fgetc(fp) = getc(fp) 모니터로 한 문자 출력 fputc(c, stdout) = putc(c, stdout ) = putchar(c ) 파일로 한 문자 출력 fputc(c, fp) = putc(c, fp) 함수의 원형 설명 int fgetc (FILE* fp); 키보드/파일로 부터 한 문자를 입력 받는다. 파일의 끝에 도달 할 경우: EOF 반환 int fputc (int c, FILE* fp); 모니터/파일에 한 문자를 출력한다. 호출 실패의 경우: EOF 반환
1.3 파일 유형별 입.출력 함수 한 행(line) 입출력 키보드로부터 한 행 입력 파일로부터 한 행(line) 입력 fgets(buff, n, stdin); 키보드로부터 입력되는 값을 (n-1)만큼 buff로 읽어온다 엔터키(\n)값까지 포함시킨다. 명시된 크기(n)를 채우기 전 엔터키(\n)가 입력되면 엔터키까지만 buff로 읽어온다. gets(buff); 엔터키가 입력될 때까지 키보드로부터 입력되는 값을 buff로 읽어온다 엔터키(\n)값은 포함시키지 않는다. 파일로부터 한 행(line) 입력 fgets(buff, n, fp) 파일로부터 (n-1)만큼 또는 엔터키(\n)값까지 buff로 읽어온다 함수의 원형 설명 char* fgets (char* buff, int n, FILE* fp); 키보드/파일로 부터 문자열을 입력 받는다. 파일의 끝에 도달 할 경우: NULL 포인터 반환 int fputs (const char* buff, FILE* fp); 모니터/파일에 문자열을 출력한다. 호출 실패의 경우: EOF 반환
fgets( )/ fputs( )의 예제 1 다음 변수를 선언하라 FILE* fp; char buffer[50]; “oldfpnt.txt”을 쓰기모드(“w”)로 열어라 fp = fopen( … ) 사용 키보드로부터 buffer로 이름을 입력 받아라 fgets( … ) 사용 입력 받은 이름을 파일에 기록하라 fputs( … ) 사용 파일을 닫아라 fclose( … ) 사용
표준 입력스트림(stdin)으로부터 읽어서 fgets( )/ fputs( )의 예제 1 #include<stdio.h> int main(void) { FILE* fp; char buffer[50]; fp= fopen("oldfpnt.txt","w"); if(fp == NULL) puts("파일 열기 오류"); else{ printf("이름을 입력하시오 :" fgets(buffer,sizeof(buffer),stdin); fputs(buffer,fp); fclose(fp); } return 0; 표준 입력스트림(stdin)으로부터 읽어서 표준 파일스트림(fp)에 씀
fgets( )/ fputs( )의 예제2 #include<stdio.h> int main(void) { FILE* fp; char buffer[50]; fp= fopen("oldfpnt.txt","w"); if(fp == NULL) puts("파일 열기 오류"); else{ printf("이름을 입력하시오 : "); fgets(buffer,sizeof(buffer),stdin); fputs(buffer,fp); fclose(fp); } return 0; 다음 명령문을 EOF가 입력되지 않는 동안 ((CTRL+Z)이 눌릴때까지) 반복하도록 수정하시오
fgets( )/ fputs( )의 예제2 -수정결과 #include<stdio.h> int main(void) { FILE* fp; char buffer[50]; fp= fopen("oldfpnt.txt","w"); if(fp == NULL) puts("파일 열기 오류"); else{ printf("이름을 입력하시오(종료 : Ctrl+z) : "); while( (fgets(buffer,sizeof(buffer),stdin)) != NULL) { fputs(buffer,fp); } fclose(fp); } return 0;
실패시 리턴값 NULL(0) 반환 EOF(-1) 반환 fopen, fgets fclose, fgetc, fputc, fputs, fscanf, fprintf
파일 복사하기 예제 파일 이름 두개를 입력받는다. 이미 text2.txt가 존재하는 경우 덮어쓸지 물어본 다. 원본 파일 이름을 입력하시오 : test.txt 저장할 파일 이름을 입력하시오 : test2.txt test.txt를 text2.txt로 복사한다. 이미 text2.txt가 존재하는 경우 덮어쓸지 물어본 다. Y를 입력한 경우만 test2.txt를 덮어씌우고 N이 입력되면 그냥 종료 text2.txt가 존재하지 않으면 원본 파일을 복사해 저장한다.
파일 복사 화면
#include<stdio.h> void filecopy(FILE *source, FILE *target); void main(void) { char sfile[20], tfile[20]; FILE *source, *target; char answer; printf("원본 파일을 입력하시오. : "); // puts ("원본… "); 와 동일 gets(sfile); // scanf("%s", sfile); fflush(stdin);와 동일 printf("저장할 파일을 입력하시오. : "); gets(tfile); source = fopen(sfile, "r"); // 읽기 전용으로 열기 if(source == NULL) { printf("%s 파일이 존재하지 않습니다.\n", sfile); return; }
else if ((target = fopen(tfile, "r+")) != NULL) { // 파일이 이미 존재 printf("%s 파일이 존재합니다. 덮어쓰시겠습니까? : (y/n)", tfile); while( answer != 'y' && answer != 'n') answer = getchar(); if (answer == 'y') filecopy(source, target); } else { target = fopen(tfile, "w"); // 존재하지 않으므로 새로 만듬 fclose(source); fclose(target); puts("파일 복사를 종료합니다.\n"); 대소문자 변환 : tolower(), toupper() / ctype.h ex) answer = tolower(getchar());
void filecopy(FILE *source, FILE *target) { char buffer[50]; int i = 1; while( (fgets(buffer,sizeof(buffer),source)) != NULL) { fputs(buffer,target); printf("%d..", i++); } puts("\n");
Main에 매개변수 넘겨주기 void main(int argc, char *argv[]) argc : 매개변수 개수 예) filecopy a.txt b.txt argc = 3 argv[0] = “filecopy” argv[1] = “a.txt” argv[2] = “b.txt”
void main(int argc, char *argv[]) { FILE *source, *target; char answer; if(argc != 3) { printf("[형식] filecopy 원본파일이름 저장할파일이름\n”); return; } printf("원본 파일 : %s\n", argv[1]); printf("저장 파일 : %s\n ", argv[2]); source = fopen(argv[1], "r"); if(source == NULL) { printf("%s 파일이 존재하지 않습니다.\n", argv[1]); else if ((target = fopen(argv[2], "r+")) != NULL) { // 파일이 이미 존재 printf("%s 파일이 존재합니다. 덮어쓰시겠습니까? : (y/n)", argv[2]); while( answer != 'y' && answer != 'n') answer = getchar(); // answer = getc(stdin); 과 동일 if (answer == 'y') filecopy(source, target); else { target = fopen(argv[2], "w"); // 존재하지 않으므로 새로 만듬
1.3 파일 유형별 입.출력 함수 형식이 있는 자료형(레코드) 단위 입출력 헤더파일: <stdio.h> 함수의 원형 설명 int fscanf (FILE* fp, const char* format, …); 키보드/파일로 부터 자료형에 맞춰 데이터를 입력한다. 파일의 끝에 도달한 경우: EOF 반환 int fprintf (FILE* fp, const char* format, …); 모니터/파일에 자료형에 맞춰 데이터를 출력한다.
1.3 파일 유형별 입.출력 함수 fscanf( )/ fprintf( ) 사용 예 #include<stdio.h> int main(void) { FILE* fp; char name[20]; int kor, eng, total; printf("1. 이름입력: "); fscanf(stdin,"%s",name); // 키보드로부터 데이터를 입력 printf("2. 국어점수, 영어점수입력: "); fscanf(stdin,"%d %d",&kor, &eng); // 키보드로부터 데이터를 입력 total = kor + eng; fp = fopen("data.txt","w"); fprintf(fp,"%s %d %d %d \n", name, kor, eng, total); //data.txt에 출력 fprintf(stdout,"%s %d %d %d \n", name, kor, eng, total); // 모니터에 출력 fclose(fp); return 0; }
p236 atoi() 함수때문에 필요 getch() 함수때문에 필요 #include <string.h> 지정된 문자열(STR)을 int 형으로 변환 숫자로 인식 가능한 문자가 존재하지 않는다면 0을 리턴 예) atoi(“123abc” ) -> 123 예) atoi(“1234”) -> 1234 예) atoi(“abc123”) -> 0 (zero_check(bunho) || strlen(str) > 4) #include <string.h>
P236 SUB FUNCTION Y n==0인경우 숫자로 인식 가능한 문자가 존재하지 않는 경우로서 1를 리턴 숫자로 인식 가능한 문자가 존재하지 않는 경우로서 1를 리턴 Y toupper( ) 함수 지정된 문자를 대문자로 변환한다
p237 “C:\\newfile.dat <stdlib.h> 에 정의됨
학번 9자리와 이름 입력 학번 숫자 9자리와 이름을 계속 입력받아 현재 디렉토리에 student.txt 파일에 저장하고 순서대로 읽어서 출력하는 프로그램을 작성하시오.
#include <stdio.h> // standard input/output #include <stdlib.h> // standartd library #include <conio.h> // console input/output #include <string.h> // string int zero_check(int n); int more_data( ); void main( ) { FILE *dfpnt; long bunho; char *str, name[10]; char *filename = ".\\newfile.dat"; str = (char *) malloc(10); dfpnt = fopen(filename,"w"); do { printf(“\n\n학번="); gets(str); bunho = atoi(str); } while (zero_check(bunho) || strlen(str) != 9 ); printf("이름="); gets(name); fprintf(dfpnt, “ %9d %10s ", bunho, name); } while (more_data( )); printf("\n"); fclose(dfpnt);
if ((dfpnt = fopen(filename,"r")) == NULL) { printf("\n input file open error"); exit(1); // <stdlib.h> 에 정의됨 } while(fscanf(dfpnt, “ %9d %10s ", &bunho, name) != EOF) printf("\n%9d-%10s\n", bunho, name); fclose(dfpnt); int zero_check(int n) if (n) return 0; else return 1; int more_data( ) printf("\n계속 하시겠습니까?(y/n)="); if (tolower(getch( )) == 'y') return 1; else return 0;
1.3 파일 유형별 입.출력 함수 파일의 끝을 확인하는 방법 단점 단점 해결 ‘파일 끝에서 반환되는 값이 함수마다 다르다.’ feof()함수 함수 파일의 끝에서 반환하는 값 fgetc( ) EOF(-1) fgets( ) NULL(0) fscanf( )
1.3 파일 유형별 입.출력 함수 파일의 끝을 검사하는 feof()함수 함수 원형 설명 int feof(FILE* fp); 파일포인터가 파일의 끝에 도달했는지 아닌지를 검사 파일의 끝에 도달 : 0이 아닌 값 반환 파일의 끝에 도달하지 못한 경우 : 0 반환
feof( ) 함수 예 (p237 예제 수정) “C:\\newfile.dat” 다음 while 조건문을 feof( ) 함수를 이용하여 EOF를 확인하도록 바꾸시오
feof( ) 함수 예 - 수정결과 while( !feof(infpnt) ) { fscanf(infpnt, “ %4d %10s ”, &bunho, name); printf(“\n%4d-%10s”, bunho, name); } “C:\\newfile.dat”
1.3 파일 유형별 입.출력 함수 버퍼를 비우는 fflush( )함수 버퍼(Buffer) 처리할 데이터를 임시로 저장하는 장소 입력 버퍼 : 입력 데이터를 저장하기 위한 버퍼 출력 버퍼 : 출력 데이터를 저장하기 위한 버퍼 함수 원형 설명 int fflush(FILE* fp); 버퍼를 비움 실패 : EOF 반환 stdout stdin
1.3 파일 유형별 입.출력 함수 버퍼링으로 인한 문제 21\n 21 \n #include <stdio.h> int main(void) { int age; char name[20]; printf("나이입력: "); scanf("%d",&age); //fflush(stdin); // 입력 버퍼를비운다. printf("이름을 입력: "); fgets(name, sizeof(name), stdin); printf("%d\n",age); printf("%s\n",name); return 0; } 21\n 21 \n
1.3 파일 유형별 입.출력 함수 문제가 생기는 이유 문제점 해결 fflush(stdin)함수를 호출함으로써 입력버퍼를 비운다.
1.4 레코드 포인터(p238) fseek( ) 함수 두번째 인수(offset ) 음수일때-> 파일포인터를 앞쪽으로 이동 양수일때-> 파일포인터를 뒤쪽으로 이동(0 일때는 제자리에) 세번째 인수(origin ) 함수 원형 설명 int fseek(FILE* fp, long offset, int origin); origin부터 offset만큼 파일포인터를 이동시킨다. 성공 : 0 반환, 실패 : 0이 아닌 값 반환 기호 상수 값 설명 SEEK_SET 파일의 시작 위치 SEEK_CUR 1 파일의 현재 위치 SEEK_END 2 파일의 끝 위치
1.4 레코드 포인터 fseek(파일 포인터이름, 0, SEEK_SET); fseek(파일 포인터이름, 2,SEEK_SET);
1.4 레코드 포인터 fseek(파일 포인터이름, -1, SEEK_END);
1.4 레코드 포인터 SEEK_CUR의 위치 fseek(파일포인터이름, -2, SEEK_CUR);
ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ ?? fseek( ) 함수 사용 예 #include <stdio.h> int main(void) { FILE* fp; fp=fopen("seek.txt", "w"); // 쓰기 모드 fputs("ABCDEFGHIJ", fp); fclose(fp); fp=fopen("seek.txt", "r"); // 읽기 모드 fseek(fp, 0, SEEK_SET); fprintf(stdout, "%c \n", fgetc(fp)); fseek(fp, 2, SEEK_SET); fseek(fp, -1, SEEK_END); fseek(fp, -2, SEEK_CUR); return 0; } ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ ??
예제 example.txt 파일을 생성(“w+”이용)하여 "This is an apple" 을 쓰고 화면에 표시(fputs이 용) 다시 fseek 함수를 이용하여 n 부터 “ sam” 으로 4개의 문자열을 바꾼다. (fseek, fputs이용) 즉, example.txt 에는 "This is a sample" 이 들어가게 된다. fseek을 이용하여 파일의 맨 처음으로 가서 한 문 장을 읽어 화면에 출력한다. (fseek, fgets, fputs 사용)
#include <stdio.h> int main () { FILE * pFile; char temp[50]; pFile = fopen ( "example.txt" , "w+" ); fputs ( "This is an apple." , pFile ); // 파일에 저장 fputs ( "This is an apple." , stdout ); // 화면에 출력 fseek ( pFile , 9 , SEEK_SET ); // 현재위치에서 9바이트뒤 fputs ( " sam" , pFile ); // “ sam”을 저장 fseek ( pFile, 0, SEEK_SET ); // 맨 처음으로 이동 fgets ( temp, sizeof(temp), pFile ); // temp에 가져오기 fputs ( "\n변신 : ", stdout ); // 화면에 출력 fputs ( temp, stdout ); // temp 화면에 출력 fclose ( pFile ); return 0; }
1.4 레코드 포인터(p237) ftell( ) 함수 파일의 시작위치로부터 떨어진 거리를 알려준다 읽기/쓰기 작업의 위치로서 함수 원형 설명 long ftell(FILE* fp); 파일 포인터의 위치를 확인 성공 : 파일 포인터의 위치 반환 실패 : EOF 반환 읽기/쓰기 작업의 위치로서 파일의 시작부분에서 부터의 offset 바이트 수
ABCDEFGHIJ ftell( ) 함수 사용 예1 1. 끝에서 -8이동 fgetc에 의해 1바이트 이동 #include <stdio.h> int main(void) { FILE* fp; long distance; fp=fopen("ftell.txt", "w"); // 쓰기모드 fputs("ABCDEFGHIJ", fp); fclose(fp); fp=fopen("ftell.txt", "r"); // 읽기모드 fseek(fp, -8, SEEK_END); fprintf(stdout, "%c \n", fgetc(fp)); distance=ftell(fp); printf("거리: %ld \n", distance); return 0; } ABCDEFGHIJ 3. ftell 거리 = 3 fgetc에 의해 1바이트 이동
ftell( ) 함수 사용 예2 파일 사이즈 구하기 #include<stdio.h> int main(void) { FILE* fp = fopen("ftell.txt", "rb"); fseek(fp, 0, SEEK_END); printf("ftell.txt 파일의 크기 : %d 바이트\n", ftell(fp)); fclose(fp); return 0; } [p.238 예제] 파일의 현재위치를 확인한 후 지정해준 옵셋과 origin 을 이용하여 새로운 위치로 이동시키는 프로그램을 작성
파일 크기 구하기 예제 파일의 이름을 입력받아 (char *filename, scanf) 해당 파일의 바이트수를 구해 출력하시오.(fseek, ftell이용)
#include <stdio.h> #include <stdlib.h> // malloc 함수 정의 int main(void) { FILE* fp ; // 파일 포인터 변수 char *filename; // 문자열 포인터변수 (메모리 4바이트 차지: 주소) filename = (char *) malloc(50); // filename이 50바이트의 공간을 할당받음 // 표준 출력장치(모니터)로 문자열 출력 fputs("크기를 알고 싶은 파일 이름을 입력하세요 : ", stdout); scanf("%s",filename); // 파일 이름 입력받기 fp = fopen(filename, "rb"); if (fp == NULL) { printf("%s 파일을 열 수 없습니다.\n", filename); return 1; } fseek(fp, 0, SEEK_END); printf("ftell.txt 파일의 크기 : %d 바이트\n", ftell(fp)); fclose(fp); return 0;
void *malloc(size) char *filename; // 주소값을 가지는 문자열포인터 그냥 scanf(“%s”, filename) 이용하면 run-time 오류 발생 이유 : filename이 주소값만 가지는 문자열 포인터이기때문 해결 : 문자열을 보관할 수 있는 메모리 영역을 할당하여 filename이 그 주소를 지시할 수 있게 해야함. malloc의 리턴타입은 void * 이므로 캐스트 연산해주어야 함. filename = (char *) malloc(5); 할당해제 : free(포인터변수) free(filename); filename filename+1 filename+2 filename+3 filename+4 filename
파일 이름 입력받기 test.txt\n test.txt\0 문자열만 입력받는 함수 문자열의 끝 엔터값까지 입력받는 함수 scanf("%s",filename); gets(filename); 문자열의 끝 엔터값까지 입력받는 함수 fgets(filename,50,stdin); 다음처럼 마지막 엔터값을 없애줘야함. filename[strlen(filename)-1] = '\0'; filename 변수에 저장된 문자열길이 -1에 강제로 NULL을 넣어줌 test.txt\n test.txt\0
(P238 수정) char * filename; 을 사용한다면??? #include <stdio.h> int main( ) { char filename[20]; FILE *infpnt; int offset, origin; printf("파일 이름을 입력하세요.. : "); gets(filename); printf("파일 = %s\n", filename); if ((infpnt = fopen(filename,"r")) == NULL) printf("\n%s 파일 열기 오류\n", filename); return 1; } fseek(infpnt, 0, SEEK_END); // 파일끝으로 이동 printf("\n%s 파일의 크기 : %d 바이트\n",filename, ftell(infpnt)); fseek(infpnt, 0, SEEK_SET); // 파일 현재 위치 printf("\n파일 %s의 현재 위치=%d\n", filename, ftell(infpnt)); printf("\nOrigin(0-처음, 1-현재, 2-끝)과 바이트수(offset)를 입력하시오 :"); scanf("%d,%d", &origin, &offset); fseek(infpnt, offset, origin); printf("파일 %s의 %d부터 %d위치의 내용은 = %c\n", filename, origin, offset, getc(infpnt)); printf("\n--------------------\n"); fclose(infpnt); return 0; (P238 수정) char * filename; 을 사용한다면??? char *filename = (char *) malloc(20); free(filename);
int main( ) { char filename[20], *str_origin[3] = {"처음", "현재", "끝" } ; FILE *infpnt; int offset, origin; char temp[50]; printf("파일 이름을 입력하세요.. : "); gets(filename); printf("파일 = %s\n", filename); fseek(infpnt, 0, SEEK_SET); // 파일 현재 위치 fgets(temp, 5, infpnt); printf("%s\n", temp); printf("\n파일 %s의 현재 위치=%d\n", filename, ftell(infpnt)); printf("\nOrigin(0-처음, 1-현재, 2-끝)과 바이트수(offset)를 입력하시오 :"); scanf("%d,%d", &origin, &offset); fseek(infpnt, offset, origin); printf("파일 %s의 %s부터 %d위치의 내용은 = %c\n", filename, str_origin[origin], offset, getc(infpnt)); printf("\n--------------------\n"); fclose(infpnt); return 0; }
2. 시스템 입.출력 함수 고급 입출력 함수 저급 입출력함수 = 시스템 입출력 함수 버퍼를 사용한다. 버퍼를 사용하지 않는다. 헤더파일: <stdio.h> 버퍼를 사용한다. 버퍼에 데이터를 모았다가 한번에 처리 저속, 고효율 저급 입출력함수 = 시스템 입출력 함수 헤더파일 : <io.h> 버퍼를 사용하지 않는다. 데이터를 모으지 않고 바로 처리 고속, 저효율 이식성 문제
2.1 Open( ) Open ( ) 함수 첫번째 인수 두번째 인수 세번째 인수 리턴 값 open할 파일이름 파일의 접근 모드 새 파일 생성시 새 파일의 속성 설정 리턴 값 생성된 파일 핸들(양의 정수) 함수의 원형 설명 #include<io.h> int open (const char* filename, int oflag [, int mode]); 파일 핸들을 생성하고 파일을 연다. 호출 실패의 경우: -1 반환
2.1 Open( )- 접근모드(oflag) <fcntl.h>파일에 정의 oflag 값 의미 O_APPEND 0x0001 쓰기용으로 파일을 열어, 파일의 끝을 현재위치로 설정한다. O_CREAT 0x0002 쓰기 용으로 파일을 생성한다. 파일이 이미 존재하면 효과가 없다. O_EXCEL 0x0004 O_CREAT와 함께 사용되어 파일이 이미 존재할 경우 오류값을 반환 O_RDONLY 0x0100 읽기 전용으로 파일을 연다. O_RDWR 0x0200 읽고 쓰기용으로 파일을 연다. O_TRUNC 0x0400 파일을 열고 내용을 삭제하여 파일의 길이를 0으로 만든다. O_WRONLY 0x0800 쓰기 전용으로 파일을 연다. O_BINARY 0x4000 이진 모드로 파일을 연다. O_TEXT 0x8000 텍스트 모드로 파일을 연다.
2.1 Open( )- 파일모드(mode) 대부분의 경우, 이 mode 표기는 생략 creat ( ) 함수 <fcntl.h>파일에 정의 mode 의미 S_IWRITE 쓰기 허용 S_IREAD 읽기 허용 S_IREAD | S_IWRITE 읽기와 쓰기 허용 대부분의 경우, 이 mode 표기는 생략 O_CREAT을 사용할 경우 새로운 파일에 대한 접근 허가를 명시할 때 사용 creat ( ) 함수 새 파일 생성시 open( ) 대신 creat( )를 사용. 형식: int creat (char *filename, int mode); mode는 위 open( ) 함수와 동일 실패시 -1(EOF)을 반환.
2.2 Close( ) Close( ) 함수 함수의 원형 설명 Int close (int fd); 파일을 닫는다. 호출 실패의 경우: -1 (EOF)반환
파일 fd로부터 n바이트를 읽어 buf에 저장한다 2.3 read( ) read( ) 함수 예) int i; i = read(fd, buf, 10); i에는 실제 buf로 읽어온 바이트 수가 저장된다 함수의 원형 설명 #include<io.h> int read (int fd, void * buf, int n); 파일 fd로부터 n바이트를 읽어 buf에 저장한다 EOF를 만나면: 0 (NULL) 반환 호출 실패의 경우: -1 (EOF) 반환
2.4 write( ) write( )함수 예) int i; i = write(fd, buf, 10); 함수의 원형 설명 #include<io.h> int write (int fd, const char* buf, int n); buf로부터 n바이트를 읽어와 파일에 쓴다 호출 실패의 경우: -1(EOF) 반환