C 프로그래밍프로젝트 Chap 24. 파일입출력 2013.11.27. 오병우 컴퓨터공학과
파일 (File) 입출력 표준입출력 vs. 파일입출력 HDD 프로그래머입장에서는동일한방법으로입출력 다만 file 을읽고쓰기전에 Open 해서스트림에대한파일포인터 (file pointer) 를얻어야한다. OS 가실제작업을대행하며, 프로그래머는적절한함수를적절한방법으로호출 Department of Computer Engineering 2
fopen() 함수와 FILE 구조체 FILE *fp = fopen( 파일경로및이름문자열, rb ); Read Binary Department of Computer Engineering 3
fopen() 함수 파일의개방 데이터를주고받을수있는스트림의생성 #include <stdio.h> FILE* fopen (const char * filename, const char * mode) 성공시해당파일의파일포인터, 실패시 NULL 포인터리턴 FILE* f = fopen( c:\\my Documents\\test.dat, rb ); 파일이름 (filename) full path + filename : 절대경로 현재디렉터리기준의 filename: 상대경로
fopen() 함수의 mode 기준 1 읽기위한스트림이냐? 쓰기위한스트림이냐? 파일에데이터를쓰는데사용하는스트림과데이터를읽는데사용하는스트림은구분이된다. 기준 2 텍스트데이터를위한스트림이냐? 바이너리데이터를위한스트림이냐? 출력의대상이되는데이터의종류에따라서스트림은두가지로나뉜다.. 텍스트데이터 텍스트데이터읽기스트림 읽기스트림 바이너리데이터 바이너리데이터읽기스트림 쓰기스트림 텍스트데이터바이너리데이터 텍스트데이터쓰기스트림바이너리데이터쓰기스트림 기본적인스트림의구분! 그러나실제로는더세분화! Department of Computer Engineering 5
파일개방모드 fopen() 함수의 mode 파일접근모드 + 데이터입 출력모드 파일접근모드 개방한파일의사용용도를결정 데이터입출력모드 모드 t b 의미 텍스트모드 (text mode) 2 진모드 (binary mode) Department of Computer Engineering 6
Mode 조합 r w a r+ w+ a+ Read or Write b t Binary or Text rb 바이너리데이터읽기스트림 wt a+t 텍스트데이터읽기덧붙이기스트림 텍스트데이터쓰기스트림 Department of Computer Engineering 7
텍스트모드 CR & LF CR(Carriage Return) 은특수문자 '\r' 로표시 LF(Line Feed) 는특수문자 '\n' 로표시 New Line Department of Computer Engineering 8
Text Mode and Binary Mode 텍스트모드와 2 진모드의차이점 2진모드 : 데이터타입과관계없이 2진수로입출력 텍스트모드 : 텍스트로변경하여입출력 CR-LF 자동변환 Unix/Linux 에서는이진모드와텍스트모드구별없음 Department of Computer Engineering 9
Text Mode 개행정보를정확히저장하기위해서는위와같은종류의변환과정을거쳐야한다. 텍스트모드로데이터를입출력하면이러한형태의변환이운영체제에따라서자동으로이뤄진다. Department of Computer Engineering 10
FILE 구조체의포인터 fopen 함수의리턴타입 흔히파일포인터라불린다. FILE 구조체 개방한파일에대한여러가지정보를지니는변수를가리키는포인터 FILE 구조체포인터의용도 데이터입 출력함수의호출 위치정보의참조 파일의끝확인 현재어디까지 read(write) 했는지현재위치저장 Department of Computer Engineering 11
파일의종결 (CLOSE) 스트림의종결을의미함 fclose() 함수 #include <stdio.h> int fclose (FILE * stream) 종료가오류없이제대로이뤄지면 0 을리턴 사용이끝났을때즉시종결할것을권장함 프로그램종료시자동종결 왜일부러닫아주는것일까? 시스템오류에대한안전성확보» 쓰기버퍼» Cf.) 데이터베이스의 Commit Department of Computer Engineering 12
fopen() 과 fclose() #include <stdio.h> int main (void) { int state; FILE* file = fopen( Test.txt, wt ); if (file == NULL) { // 시스템함수호출시매번체크할것 printf( file open error!\n ); return 1; } } state=fclose(file); if (state!=0) { printf( file close error! \n ); return 1; } return 0; Department of Computer Engineering 13
Text Mode 입 출력함수 스트림기능 키보드 / 모니터선택 ( 키보드 / 모니터, 파일 ) 문자출력 int putchar(int c) int fputc(int c, FILE* stream) 문자입력 int getchar(void) int fgetc(file* stream) 문자열출력 문자열입력 형식지정출력 형식지정입력 int puts(const char* s) char* gets(char* s) int printf( const* format,...) int scanf( const char* format,...) int fputs (const char* s, FILE* stream) char* fgets (char* s, int n, FILE* stream) int fprintf(file* stream, const char* format,...) int fscanf(file* stream, const char* format,...) Department of Computer Engineering 14
스트림입출력예제 /* fputs */ Text Mode 예제 /* fgets */ #include <stdio.h> #include <stdio.h> int main (void) { FILE *fp = fopen( Test.txt, wt ); if (fp == NULL) // 오류처리 puts ( Don t worry! ); fputs ( Don t worry!, stdout); fputs ( Don t worry!, fp); fclose (fp); } return 0; int main (void) { char buf[30]; FILE *fp = fopen( Test.txt, rt ); if (fp == NULL) // 오류처리 fputs( 데이터입력 :, stdout); fgets(buf, sizeof(buf), stdin); puts(buf); } fgets(buf, sizeof(buf), fp); puts(buf); return 0; Department of Computer Engineering 15
양식화된입출력예제 Text Mode 예제 /* fprintf_fscanf */ FILE *fp = fopen( Test.txt, wt ); for (i=2; i<10; i++) for (j=1; j<10; j++) fprintf(fp, %d * %d = %d\n, i, j, i*j); fclose(fp); fp = fopen ( Test.txt, rt ); for (i=2; i<10; i++) for (j=1; j<10; j++) { fscanf(fp, %d %c %d %c %d, &a, &c1, &b, &c2, &c); printf( %d %c %d %c %d \n, a, c1, b, c2, c); } fclose (fp); Department of Computer Engineering 16
File 의끝 (End of File, EOF) 리턴값참조에의한구분 함수 fgetc fgets fscanf 파일의끝에서리턴되는값 EOF(-1) NULL 포인터 (0) EOF(-1) feof() 함수를사용하는방법 FILE 구조체변수를참조 #include <stdio.h> Test Mode ( rt 또는 r ) 사용시이방법사용추천 int feof(file * stream) 파일의끝에도달한경우 0 이아닌값을리턴 Department of Computer Engineering 17
Text Mode 파일복사프로그램 문자단위파일복사프로그램 파일의끝을확인해야하는경우이함수가필요하다. 파일입력함수는오류가발생하는경우에도 EOF 를 반환한다. 따라서 EOF 의반환원인을확인하려면이 함수를호출해야한다. EOF 가반환이되면... feof 함수호출을통해서 EOF 반환원인을확인! Department of Computer Engineering 18
Binary Mode 입력 int main(void) { int buf[12];.... fread((void*)buf, sizeof(int), 12, fp);.... sizeof(int) 크기의데이터 12 개를 fp 로부터 읽어들여서배열 buf 에저장하라! Department of Computer Engineering 19
Binary Mode 출력 int main(void) { int buf[7]={1, 2, 3, 4, 5, 6, 7};.... fwrite((void*)buf, sizeof(int), 7, fp);.... sizeof(int) 크기의데이터 7 개를 buf 로부터 읽어서 fp 에저장해라! Department of Computer Engineering 20
Binary Mode 파일복사프로그램 20 Bytes 씩 1. 2. 1. 파일의끝에도달해서 buf 를다채우지못한경우에참이된다! 2. feof 함수호출의결과가참이면파일의끝에도달했다는의미이므로마지막으로읽은데이터를파일에저장하고프로그램을종료한다! Department of Computer Engineering 21
Binary Mode 파일복사프로그램 #include <stdio.h> char *filename = in.dat ; struct S { int a, b; double d; char str[103]; }; int main(void) { struct S buffer; int items_read = 0; FILE *in_file = fopen(filename, rb ); 1 Byte 씩 } while (fread( (struct S*) &buffer, sizeof(struct S), 1, in_file) == 1) items_read++; if (ferror(in_file)) { fprintf(stderr, Read error, file %s record %d\n, filename, items_read+1); exit(1); } printf( Finished: %d elements read\n, items_read); return 0; Department of Computer Engineering 22
Random Access 파일위치지시자 (R/W Pointer) FILE 구조체변수의멤버로서존재 READ & WRITE 에대한위치정보가된다. 입 출력함수의호출에의해자동으로이동 순차적 (sequential) 입출력 : 순방향차례대로입출력 임의입출력 (random access) 시에는위치지시자를프로그래머가변경할수있어야한다. Department of Computer Engineering 23
파일위치지시자 FILE 구조체의멤버중하나. read 모드로오픈된파일위치지시자 : 어디까지읽었더라? 에대한답 write 모드로오픈된파일위치지시자 : 어디부터이어서쓰더라? 에대한답 즉, Read/Write에대한위치정보를갖고있다. 따라서파일입출력과관련이있는 fputs, fread, fwrite 와같은함수가호출될때마다파 일위치지시자의참조위치는변경이된다. Department of Computer Engineering 24
Random Access fseek() 함수 특정위치임의접근방식의입 출력 관련함수 : fseek() 파일위치지시자를 wherefrom에서부터 offset만큼의위치로이동 #include <stdio.h> int fseek(file * stream, long offset, int wherefrom) 성공시 0을, 실패시 0이아닌값을리턴한다. wherefrom SEEK_SET(0) 파일위치지시자설정 파일의맨앞 SEEK_CUR(1) 현재위치 ( 이동하지않는다 ) SEEK_END(2) 파일의끝 Department of Computer Engineering 25
fseek() 함수 파일위치지시자의 참조위치를변경시키는함수 fseek 함수의호출결과로인한파일위치지시자의이동결과 Department of Computer Engineering 26
fseek 함수의사용예제 fseek() 예제 char buf[10]; fgets(buf, 7, file); printf( %s \n, buf); fseek(stream, 0, SEEK_END) fseek(file, 2, SEEK_CUR); //fseek(file, -2, SEEK_CUR); //fseek(file, 2, SEEK_SET); //fseek(file, -2, SEEK_END); 현재상태의 ftell(stream) 은 6 Department of Computer Engineering 27
fseek() 예제 1 2 3 4 5 6 7 8 9 e(eof) 1 2 3 4 5 6 7 8 9 e(eof) 1 2 3 4 5 6 7 8 9 e(eof) 1 2 3 4 5 6 7 8 9 e(eof) 1 2 3 4 5 6 7 8 9 e(eof) 1 2 3 4 5 6 7 8 9 e(eof) 실행결과 Department of Computer Engineering 28
ftell() 함수 현재파일위치자의위치정보를반환하는함수! 맨뒤로이동 현재위치저장 저장해놓은위치복원 실행결과 Department of Computer Engineering 29
File Size FILE *fp = NULL; int i; int filesize = 0; unsigned char ch; fp = fopen(argv[1], "rb"); if (fp == NULL) { printf("file Open Error: %s\n", argv[1]); return 1; } 이렇게해도됨 //filesize = _filelength(_fileno(fp)); // io.h 를 include 해야함 fseek(fp, 0, SEEK_END); filesize = ftell(fp); fseek(fp, 0, SEEK_SET); for (i = 0; i < filesize; i++) { fread(&ch, sizeof(unsigned char), 1, fp); printf("%c ", ch); } fclose(fp); Department of Computer Engineering 30
파일처리함수 다른유용한함수 void rewind (FILE* stream) // == fseek(stream, 0L, SEEK_SET) 파일위치지시자를맨앞으로이동한다. int remove (const char * filename) 파일을삭제한다. 성공할경우 0, 실패시 0 이아닌값을반환한다. 사용예 long int offset = ftell (file); rewind (file); fseek (file, offset, SEEK_SET); Department of Computer Engineering 31
연습문제 파일을복사하는프로그램 C:> copy afile bfile #include <stdio.h> int main (int argc, char *argv[]) { char c; FILE *src, *dest; if (argc!= 3) { puts( usage: copy src dest\n ); return 1; } src = fopen(argv[1], rb ); dest = fopen(argv[2], wb ); if (src == NULL dest == NULL) { // 오류처리 } } while (1) { c = fgetc(src); if (feof(src)!=0) break; fputc(c, dest); } fclose (src); fclose (dest); return 0; data 가저장된순서나 type 을모르므로 이진모드로처리한다. 문자 (char) 단위라기보다 byte 단위의 의미로사용함. Department of Computer Engineering 32