파일입출력 IT CookBook, 유닉스시스템프로그래밍
학습목표 유닉스에서파일입출력의특징을이해한다. 저수준파일입출력함수를사용할수있다. 고수준파일입출력함수를사용할수있다. 임시파일을생성해파일입출력을할수있다. 2/51
목차 저수준파일입출력 파일기술자 파일생성과열고닫기 파일읽기와쓰기 파일오프셋지정 파일기술자복사 파일기술자제어 파일삭제 고수준파일입출력 파일포인터 파일열기와닫기 문자기발입출력 문자열기반입출력 버퍼기반입출력 형식기반입출력 파일오프셋지정 파일기술자와파일포인터간변환 임시파일사용 임시파일명생성 임시파일포인터생성 3/51
파일기술자 파일기술자 현재열려있는파일을구분하는정수값 저수준파일입출력에서열린파일을참조하는데사용 0번 : 표준입력, 1번 : 표준출력, 2번 : 표준오류 4/51
파일생성과열고닫기 [1] 파일열기 : open(2) #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int open(const char *path, int oflag [, mode_t mode]); path 에지정한파일을 oflag 에지정한플래그값에따라열고파일기술자를리턴 oflag 값 종류 기능 O_RDONLY 파일을읽기전용으로연다. O_WRONLY 파일을쓰기전용으로연다. O_RDWR 파일을읽기와쓰기가가능하게연다. O_CREAT O_EXCL 파일이없으면파일을생성한다 O_CREAT 옵션과함께사용할경우기존에없는파일이면파일을생성하지만, 파일이이미있으면파일을생성하지않고오류메시지를출력한다. O_APPEND 파일의맨끝에내용을추가한다. O_TRUNC 파일을생성할때이미있는파일이고쓰기옵션으로열었으면내용을모두지우고파일의길이를 0 으로변경한다. O_NONBLOCK/O_NDELAY 비블로킹 (Non-blocking) 입출력 O_SYNC/O_DSYNC 저장장치에쓰기가끝나야쓰기동작을완료 5/51
파일생성과열고닫기 [2] 파일열기 : open(2) mode : 파일접근권한지정, 0644 같이숫자나플래그값으로지정가능 mode=s_irusr S_IWUSR; 6/51
파일생성과열고닫기 [3] 파일생성 : creat(2) #include <sys/stat.h> #include <fcntl.h> int creat(const char *path, mode_t mode); 파일생성함수, open 함수에파일생성기능이없던구버전유닉스에서사용 open 함수와달리옵션을지정하는부분이없다. creat 함수로파일을생성하면파일기술자를리턴하므로별도로 open 할필요없음 파일닫기 : close(2) #include <unistd.h> int close(int fildes); 프로세스에서열수있는파일개수가제한되어있으므로파일의사용이끝나면닫아야한다. 7/51
[ 예제 2-1] 새파일열고닫기 ex2_1.c 01 #include <sys/types.h> 02 #include <sys/stat.h> 03 #include <fcntl.h> 04 #include <unistd.h> 05 #include <stdlib.h> 06 #include <stdio.h> 07 08 int main(void) { # ls unix.txt unix.txt: 해당파일이나디렉토리가없음 # gcc -o ex2_1.out ex2_1.c # ex2_1.out# ls -l unix.txt 09 int fd; -rw-r--r-- 1 root other 0 1월 6일 13:10 unix.txt 10 mode_t mode; 11 12 mode = S_IRUSR S_IWUSR S_IRGRP S_IROTH; 13 접근권한 :644 14 fd = open("unix.txt", O_CREAT, mode); 15 if (fd == -1) { 16 perror("creat"); 17 exit(1); 18 } 19 close(fd); 20 21 return 0; 22 } 8/51
[ 예제 2-2] O_EXCL 플래그사용하기 ex2_2.c 01 #include <sys/types.h> 02 #include <sys/stat.h> 03 #include <fcntl.h> 04 #include <unistd.h> 05 #include <stdlib.h> 06 #include <stdio.h> 07 08 int main(void) { 09 int fd; 10 11 fd = open("unix.txt", O_CREAT O_EXCL, 0644); 12 if (fd == -1) { 13 perror("excl"); 14 exit(1); 15 } 16 close(fd); 17 18 return 0; 19 } # ls unix.txt unix.txt # ex2_2.out Excl: File exists # rm unix.txt # ex2_2.out # ls unix.txt unix.txt 9/51
[ 예제 2-3] 파일기술자할당 ex2_3.c 01 #include <sys/types.h> 02 #include <sys/stat.h> 03 #include <fcntl.h> 04 #include <unistd.h> 05 #include <stdlib.h> 06 #include <stdio.h> 07 08 int main(void) { 09 int fd; 10 11 close(0); 12 13 fd = open("unix.txt", O_RDWR); 14 if (fd == -1) { 15 perror("excl"); 16 exit(1); 17 } 18 19 printf("unix.txt : fd = %d\n", fd); 20 close(fd); 21 22 return 0; 23 } # ex2_3.out unix.txt : fd = 0 11 행에서 0 번을닫았으므로새로생성한파일은가장작은번호인 0 번이할당된다. 10/51
파일읽기와쓰기 파일읽기 : read(2) #include <unistd.h> ssize_t read(int fildes, void *buf, size_t nbytes); 파일에서 nbytes 로지정한크기만큼바이트를읽어서 buf 에저장 실제로읽어온바이트개수를리턴 리턴값이 0 이면파일의끝에도달했음을의미 파일의종류에상관없이무조건바이트단위로읽어온다. 파일쓰기 : write(2) #include <unistd.h> ssize_t write(int fildes, const void *buf, size_t nbytes); buf 가가리키는메모리에서 nbytes 로지정한크기만큼파일에기록 실제로쓰기를수행한바이트수를리턴 11/51
[ 예제 2-4] 파일읽기 ex2_4.c 01 #include <fcntl.h> 02 #include <unistd.h> 03 #include <stdlib.h> 04 #include <stdio.h> 05 06 int main(void) { 07 int fd, n; 08 char buf[10]; 09 10 fd = open("unix.txt", O_RDONLY); 11 if (fd == -1) { 12 perror("open"); 13 exit(1); 14 } 15 16 n = read(fd, buf, 6); 17 if (n == -1) { 18 perror( Read"); 19 exit(1); 20 } 21 12/51
[ 예제 2-4] 파일읽기 22 buf[n] = '\0'; 23 printf("n=%d, buf=%s\n", n, buf); 24 close(fd); 25 return 0; 26 } # cat unix.txt Unix System Programming # ex2_4.out n=6, buf=unix S 13/51
[ 예제 2-5] 파일읽고쓰기 ex2_5.c... 06 int main(void) { 07 int rfd, wfd, n; 08 char buf[10]; 09 10 rfd = open("unix.txt", O_RDONLY); 11 if(rfd == -1) { perror("open unix.txt"); 13 exit(1); 14 } 15 파일기술자 2 개선언 16 wfd = open("unix.bak", O_CREAT O_WRONLY O_TRUNC, 0644); 17 if (wfd == -1) { 18 perror("open unix.bak"); 19 exit(1); 20 } 21 6바이트씩읽어온다 22 while ((n = read(rfd, buf, 6)) > 0) 23 if (write(wfd, buf, n)!= n) perror("write"); 24 14/51
[ 예제 2-5] 파일읽고쓰기 25 if (n == -1) perror("read"); 26 27 close(rfd); 28 close(wfd); 29 30 return 0; 31 } # ls unix.bak unix.bak: 해당파일이나디렉토리가없음 # ex2_5.out # cat unix.bak Unix System Programming 15/51
파일오프셋지정 파일오프셋위치지정 : lseek(2) #include <sys/types.h> #include <unistd.h> off_t lseek(int fildes, off_t offset, int whence); offset 으로지정한크기만큼오프셋을이동시킨다. offset 의값은 whence 값을기준으로해석한다. lseek(fd, 5, SEEK_SET); lseek(fd, 0, SEEK_END); 파일의시작에서 5 번째위치로이동 파일의끝에서 0 번째, 즉끝으로이동 파일오프셋의현재위치를알려면? cur_offset = lseek(fd, 0, SEEK_CUR); 16/51
[ 예제 2-6] 파일오프셋사용하기 ex2_6.c... 07 int main(void) { 08 int fd, n; 09 off_t start, cur; 10 char buf[256]; 11 12 fd = open("unix.txt", O_RDONLY); 13 if (fd == -1) { 14 perror("open unix.txt"); 15 exit(1); 16 } 17 18 start = lseek(fd, 0, SEEK_CUR); 19 n = read(fd, buf, 255); 20 buf[n] = '\0'; 21 printf("offset start=%d, Read Str=%s, n=%d\n", (int)start, buf, n); 22 cur = lseek(fd, 0, SEEK_CUR); 23 printf("offset cur=%d\n", (int)cur); 24 17/51
[ 예제 2-6] 파일오프셋사용하기 25 start = lseek(fd, 5, SEEK_SET); 26 n = read(fd, buf, 255); 27 buf[n] = '\0'; 28 printf("offset start=", Read Str=%s", (int)start, buf); 29 30 close(fd); 31 32 return 0; 33 } # ex2_6.out Offset start=0, Read Str=Unix System Programming, n=24 Offset cur=24 Offset start=5, Read Str=System Programming 18/51
파일기술자복사 파일기술자복사 : dup(2) #include <unistd.h> int dup(int fildes); 기존파일기술자를인자로받아새로운파일기술자를리턴 새로운파일기술자는현재할당할수있는파일기술자중가장작은값으로자동할당 파일기술자복사 : dup2(3) #include <unistd.h> int dup2(int fildes, int fildes2); 새로운파일기술자를지정할수있다. 19/51
[ 예제 2-7] 파일기술자복사하기 ex2_7.c 01 #include <fcntl.h> 02 #include <unistd.h> 03 #include <stdlib.h> 04 #include <stdio.h> 05 06 int main(void) { 07 int fd, fd1; 08 09 fd = open("tmp.aaa", O_CREAT O_WRONLY O_TRUNC, 0644); 10 if (fd == -1) { 11 perror("create tmp.aaa"); 12 exit(1); 13 } 14 표준출력 (1) 을닫았다 15 close(1); 16 17 fd1 = dup(fd); fd를복사하면가장작은값인 1로복사 18 19 printf("dup FD=%d\n", fd1); 20 printf("standard Output Redirection\n"); 21 close(fd); 22 23 return 0; 24 } # ex2_7.out # cat tmp.aaa DUP FD=1 Standard Output Redirection 표준출력을출력한내용이파일로저장 20/51
[ 예제 2-8] dup2 함수사용하기 ex2_8.c 01 #include <fcntl.h> 02 #include <unistd.h> 03 #include <stdlib.h> 04 #include <stdio.h> 05 06 int main(void) { 07 int fd; 08 09 fd = open("tmp.bbb", O_CREAT O_WRONLY O_TRUNC, 0644); 10 if (fd == -1) { 11 perror("create tmp.bbb"); 12 exit(1); 13 } 표준출력 (1) 로 14 지정하여복사 15 dup2(fd, 1); 16 17 printf("dup2 : Standard Output Redirection\n"); 18 close(fd); 19 20 return 0; 21 } 표준출력을출력한내용이파일로저장된다. # ex2_8.out # cat tmp.bbb DUP2 : Standard Output Redirection 21/51
파일기술자제어 파일기술자제어 : fcntl(2) #include <sys/types.h> #include <unistd.h> #include <fcntl.h> int fcntl(int fildes, int cmd, /* arg */...); 파일기술자가가리키는파일에 cmd 로지정한명령을수행 cmd 의종류에따라인자 (arg) 를지정할수있음 자주사용하는 cmd 22/51
[ 예제 2-9] fcntl 함수로파일기술자제어하기 ex2_9.c 07 int main(void) { 08 int fd, flags; 09 10 fd = open("unix.txt", O_RDWR); 11 if (fd == -1) { 12 perror("open"); 13 exit(1); 14 } 15 16 if ((flags = fcntl(fd, F_GETFL)) == -1) { 17 perror("fcntl"); 18 exit(1); 19 } 20 21 flags = O_APPEND; 22 23 if (fcntl(fd, F_SETFL, flags) == -1) { 24 perror("fcntl"); 25 exit(1); 26 } 27 28 if (write(fd, "Hanbit Media", 12)!= 12) perror("write"); 29 close(fd); 30 31 return 0; 32 } 파일을추가모드로수정 파일에내용추가 # cat unix.txt Unix System Programming # ex2_9.out # cat unix.txt Unix System Programming Hanbit Media 23/51
파일삭제 unlink(2) #include <unistd.h> int unlink(const char *path); path 에지정한파일의 inode 에서링크수를감소시킨다. 링크수가 0 이되면 path 에지정한파일이삭제된다. 파일뿐만아니라디렉토리 ( 빈디렉토리아니어도됨 ) 도삭제된다. remove(3) #include <stdio.h> int remove(const char *path); path 에지정한파일이나디렉토리를삭제한다. 디렉토리인경우빈디렉토리만삭제한다. 24/51
[ 예제 2-10] unlink 함수로파일삭제하기 ex2_10.c 01 #include <unistd.h> 02 #include <stdlib.h> 03 #include <stdio.h> 04 05 int main(void) { 06 int cnt; 07 tmp.aaa 파일삭제 08 cnt = unlink("tmp.aaa"); 09 if (cnt == -1) { 10 perror("unlink tmp.aaa"); 11 exit(1); 12 } 13 14 printf("unlink tmp.aaa success!!!\n"); 15 16 return 0; 17 } # ls -l tmp* -rw-r--r-- 1 root other 37 1월 6일 17:50 tmp.aaa -rw-r--r-- 1 root other 35 1월 6일 18:06 tmp.bbb # ex2_10.out Unlink tmp.aaa success!!! # ls -l tmp* -rw-r--r-- 1 root other 35 1월 6일 18:06 tmp.bbb 25/51
파일포인터 고수준파일입출력 : 표준입출력라이브러리 파일포인터 고수준파일입출력에서열린파일을가리키는포인터 자료형으로 FILE * 형을사용 -> 구조체에대한포인터 26/51
파일열기와닫기 [1] 파일열기 : fopen(3) #include <stdio.h> FILE *fopen(const char *filename, const char *mode); filename 으로지정한파일을 mode 로지정한모드에따라열고파일포인터를리턴 mode 값 FILE *fp; fp = fopen("unix.txt", "r"); 27/51
파일열기와닫기 [2] 파일닫기 : fclose(3) #include <stdio.h> int fclose(file *stream); fopen 으로오픈한파일을닫는다. FILE *fp; fp = fopen("unix.txt", "r"); fclose(fp); 28/51
문자기반입출력함수 문자기반입력함수 : fgetc(3), getc(3), getchar(3), getw(3) #include <stdio.h> int fgetc(file *stream); int getc(file *stream); int getchar(void); int getw(file *stream); fgetc : 문자한개를 unsigned char 형태로읽어온다. getc, getchar : 매크로 getw : 워드단위로읽어온다. 문자기반출력함수 : fputc(3), putc(3), putchar(3), putw(3) #include <stdio.h> int fputc(int c, *stream); int putc(int c, *stream); int putchar(int c); int putw(int w, FILE *stream); 29/51
[ 예제 2-11] 문자기반입출력함수사용하기 ex2_11.c 01 #include <stdlib.h> 02 #include <stdio.h> 03 04 int main(void) { 05 FILE *rfp, *wfp; 06 int c; 07 08 if ((rfp = fopen("unix.txt", "r")) == NULL) { 09 perror("fopen: unix.txt"); 10 exit(1); 11 } 12 13 if ((wfp = fopen("unix.out", "w")) == NULL) { 14 perror("fopen: unix.out"); 15 exit(1); 16 } 17 18 while ((c = fgetc(rfp))!= EOF) { 19 fputc(c, wfp); 20 } 21 22 fclose(rfp); 23 fclose(wfp); 24 25 return 0; 26 } EOF 를만날때까지한문자씩읽어서파일로출력 # cat unix.txt Unix System Programming # ex2_11.out # cat unix.out Unix System Programming 30/51
문자열기반입출력 문자열기반입력함수 : gets(3), fgets(3) #include <stdio.h> char *gets(char *s); char *fgets(char *s, int n, FILE *stream); gets : 표준입력에서문자열을읽어들인다. fgets : 파일 (stream) 에서 n 보다하나적게문자열을읽어 s 에저장 문자열기반출력함수 : puts(3), fputs(3) #include <stdio.h> char *puts(const char *s); char *fputs(const char *s, FILE *stream); 31/51
[ 예제 2-12] 문자열기반입출력함수사용하기 ex2_12.c 01 #include <stdlib.h> 02 #include <stdio.h> 03 04 int main(void) { 05 FILE *rfp, *wfp; 06 char buf[bufsiz]; 07 08 if ((rfp = fopen("unix.txt", "r")) == NULL) { 09 perror("fopen: unix.txt"); 10 exit(1); 11 } 12 13 if ((wfp = fopen("unix.out", "a")) == NULL) { 14 perror("fopen: unix.out"); 15 exit(1); 16 } 17 18 while (fgets(buf, BUFSIZ, rfp)!= NULL) { 19 fputs(buf, wfp); 20 } 21 22 fclose(rfp); 23 fclose(wfp); 24 25 return 0; 26 } 한행씩 buf 로읽어서파일로출력 # ex2_12.out # cat unix.out Unix System Programming Unix System Programming 32/51
[ 예제 2-13] fread 함수로파일읽기 ex2_13.c 01 #include <stdlib.h> 02 #include <stdio.h> 03 04 int main(void) { 05 FILE *rfp; 06 char buf[bufsiz]; 07 int n; 08 09 if ((rfp = fopen("unix.txt", "r")) == NULL) { 10 perror("fopen: unix.txt"); 11 exit(1); 12 } 13 14 while ((n=fread(buf, sizeof(char)*2, 3, rfp)) > 0) { 15 buf[6] = '\0'; 16 printf("n=%d, buf=%s\n", n, buf); 17 } 18 19 fclose(rfp); 20 21 return 0; 22 } # ex2_13.out n=3, buf=unix S n=3, buf=ystem n=3, buf=progra n=3, buf=mming 33/51
버퍼기반입출력 버퍼기반입력함수 : fread(3) #include <stdio.h> size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream); 항목의크기가 size 인데이터를 nitems 에지정한개수만큼읽어 ptr 에저장 성공하면읽어온항목수를리턴 읽을항목이없으면 0 을리턴 버퍼기반출력함수 : fwrite(3) #include <stdio.h> size_t fwrite(const void *ptr, size_t size, size_t nitems, FILE *stream); 항목의크기가 size 인데이터를 nitems 에서지정한개수만큼 ptr 에서읽어서 stream 으로지정한파일에출력 성공하면출력한항목의수를리턴 오류가발생하면 EOF 를리턴 34/51
[ 예제 2-14] fwrite 함수로파일출력하기 ex2_14.c 01 #include <stdlib.h> 02 #include <stdio.h> 03 04 int main(void) { 05 FILE *rfp, *wfp; 06 char buf[bufsiz]; 07 int n; 08 09 if ((rfp = fopen("unix.txt", "r")) == NULL) { 10 perror("fopen: unix.txt"); 11 exit(1); 12 } 13 14 if ((wfp = fopen("unix.out", "a")) == NULL) { 15 perror("fopen: unix.out"); 16 exit(1); 17 } 18 19 while ((n = fread(buf, sizeof(char)*2, 3, rfp)) > 0) { 20 fwrite(buf, sizeof(char)*2, n, wfp); 21 } 22 23 fclose(rfp); 24 fclose(wfp); 25 26 return 0; 27 } 항목크기가 char 크기의 2 배, 이것을 3 개, 즉 2*3=6 바이트씩읽어서출력 # ex2_14.out # cat unix.out Unix System Programming Unix System Programming Unix System Programming 35/51
형식기반입출력 형식기반입력함수 : scanf(3), fscanf(3) #include <stdio.h> int scanf(const char *restrict format,...); int fscanf(file *restrict stream, const char *restrict format,..); fscanf 도 scanf 가사용하는형식지정방법을그대로사용한다. 성공하면읽어온항목의개수를리턴한다. 형식기반출력함수 : printf(3), fprintf(3) #include <stdio.h> int printf(const char *restrict format, /* args */...); int fprintf(file *restrict stream, const char *restrict format, /*args */..)/ fprintf 는지정한파일로형식지정방법을사용하여출력한다. 36/51
[ 예제 2-15] fscanf 함수사용하기 ex2_15.c 01 #include <stdlib.h> 02 #include <stdio.h> 03 04 int main(void) { 05 FILE *rfp; 06 int id, s1, s2, s3, s4, n; 07 08 if ((rfp = fopen("unix.dat", "r")) == NULL) { 09 perror("fopen: unix.dat"); 10 exit(1); 11 } 12 13 printf(" 학번평균 \n"); 14 while ((n=fscanf(rfp, "%d %d %d %d %d", &id,&s1,&s2,&s3,&s4))!= EOF) { 15 printf("%d : %d\n", id, (s1+s2+s3+s4)/4); 16 } 17 18 fclose(rfp); 19 20 return 0; 21 } # cat unix.dat 2009001 80 95 80 95 2009002 85 90 90 80 # ex2_15.out 학번평균 2009001 : 87 2009002 : 86 37/51
[ 예제 2-16] fprintf 함수사용하기 ex2_16.c 01 #include <stdlib.h> 02 #include <stdio.h> 03 04 int main(void) { 05 FILE *rfp, *wfp; 06 int id, s1, s2, s3, s4, n; 07 08 if ((rfp = fopen("unix.dat", "r")) == NULL) { 09 perror("fopen: unix.dat"); 10 exit(1); 11 } 12 13 if ((wfp = fopen("unix.scr", "w")) == NULL) { 14 perror("fopen: unix.scr"); 15 exit(1); 16 } 17 18 fprintf(wfp, 학번 평균 \n"); 19 while ((n=fscanf(rfp, "%d %d %d %d %d", &id,&s1,&s2,&s3,&s4))!= EOF) { 20 fprintf(wfp, "%d : %d\n", id, (s1+s2+s3+s4)/4); 21 } 22 23 fclose(rfp); 24 fclose(wfp); 25 26 return 0; 27 } # cat unix.dat 2009001 80 95 80 95 2009002 85 90 90 80 입출력에형식지정기호사용 # ex2_16.out # cat unix.scr 학번평균 2009001 : 87 2009002 : 86 38/51
파일오프셋지정 [1] 파일오프셋이동 : fseek(3) #include <stdio.h> int fseek(file *stream, long offset, int whence); stream 이가리키는파일에서 offset 에지정한크기만큼오프셋을이동 whence 는 lseek 와같은값을사용 fseek 는성공하면 0 을실패하면 EOF 를리턴 현재오프셋구하기 : ftell(3) #include <stdio.h> long ftell(file *stream); 현재오프셋을리턴. 오프셋은파일의시작에서현재위치까지의바이트수 39/51
파일오프셋지정 [2] 처음위치로오프셋이동 : rewind(3) #include <stdio.h> void rewind(file *stream); 오프셋을파일의시작위치로즉시이동 오프셋의저장과이동 : fsetpos(3), fgetpos(3) #include <stdio.h> int fsetpos(file *stream, const fpos_t *pos); int fgetpos(file *stream, fpos_t *pos); fgetpos : 파일의현재오프셋을 pos 가가리키는영역에저장 fsetpos : pos 가가리키는위치로파일오프셋을이동 40/51
[ 예제 2-17] fseek 함수사용하기 ex2_17.c... 04 int main(void) { 05 FILE *fp; 06 int n; 07 long cur; 08 char buf[bufsiz]; 09 10 if ((fp = fopen("unix.txt", "r")) == NULL) { 11 perror("fopen: unix.txt"); 12 exit(1); 13 } 14 15 cur = ftell(fp); 16 printf("offset cur=%d\n", (int)cur); 17 18 n = fread(buf, sizeof(char), 4, fp); 19 buf[n] = '\0'; 20 printf("-- Read Str=%s\n", buf); 21 22 fseek(fp, 1, SEEK_CUR); 23 24 cur = ftell(fp); 현재오프셋읽기 오프셋이동 25 printf("offset cur=%d\n", (int)cur); 26 41/51
[ 예제 2-17] fseek 함수사용하기 27 n = fread(buf, sizeof(char), 6, fp); 28 buf[n] = '\0'; 29 printf("-- Read Str=%s\n", buf); 30 31 cur = 12; 32 fsetpos(fp, &cur); 33 34 fgetpos(fp, &cur); 35 printf("offset cur=%d\n", (int)cur); 36 37 n = fread(buf, sizeof(char), 13, fp); 38 buf[n] = '\0'; 39 printf("-- Read Str=%s\n", buf); 40 41 fclose(fp); 42 43 return 0; 44 } 오프셋이동 현재오프셋읽어서지정 # ex2_17.out Offset cur=0 -- Read Str=Unix Offset cur=5 -- Read Str=System Offset cur=12 -- Read Str=Programming 42/51
파일기술자와파일포인터간변환 저수준파일입출력의파일기술자와고수준파일입출력의파일포인터는상호변환가능 파일포인터생성 : fdopen(3) #include <stdio.h> FILE *fdopen(int fildes, const char *mode); 파일기술자와모드값을받아파일포인터를생성 파일기술자생성 : fileno(3) #include <stdio.h> int fileno(file *stream); 파일포인터를인자로받아파일기술자를리턴 43/51
[ 예제 2-18] fdopen 함수사용하기 ex2_18.c 01 #include <fcntl.h> 02 #include <stdlib.h> 03 #include <stdio.h> 04 05 int main(void) { 06 FILE *fp; 07 int fd; 08 char str[bufsiz]; 09 10 fd = open("unix.txt", O_RDONLY); 11 if (fd == -1) { 12 perror("open"); 13 exit(1); 14 } 15 16 fp = fdopen(fd, "r"); 17 18 fgets(str, BUFSIZ, fp); 19 printf("read : %s\n", str); 20 21 fclose(fp); 22 23 return 0; 24 } 파일포인터생성 저수준파일입출력함수로파일오픈 고수준파일읽기함수로읽기 # ex2_18.out Read : Unix System Programming 44/51
[ 예제 2-19] fileno 함수사용하기 ex2_19.c 01 #include <unistd.h> 02 #include <fcntl.h> 03 #include <stdlib.h> 04 #include <stdio.h> 05 06 int main(void) { 07 FILE *fp; 08 int fd, n; 09 char str[bufsiz]; 10 11 fp = fopen("unix.txt", "r"); 12 if (fp == NULL) { 13 perror("fopen"); 14 exit(1); 15 } 16 17 fd = fileno(fp); 18 printf("fd : %d\n", fd); 19 20 n = read(fd, str, BUFSIZ); 21 str[n] = '\0'; 22 printf("read : %s\n", str);22 23 24 close(fd); 25 26 return 0; 27 } 고수준파일입출력함수로파일오픈 파일기술자리턴 저수준파일읽기함수로읽기 # ex2_19.out fd : 3 Read : Unix System Programming 45/51
임시파일사용 [1] 임시파일명이중복되지않도록임시파일명생성 임시파일명생성 : tmpnam(3) #include <stdio.h> char *tmpnam(char *s); 임시파일명을시스템이알아서생성 접두어지정 : tempnam(3) #include <stdio.h> char *tempnam(const char *dir, const char *pfx); 임시파일명에사용할디렉토리와접두어지정, 접두어는 5 글자까지만지원 char *fname; fname = tempnam("/tmp", "hanbit"); 46/51
임시파일사용 [2] 템플릿을지정한임시파일명생성 : mktemp(3) #include <stdlib.h> char *mktemp(char *template); 임시파일의템플릿을받아임시파일명생성 템플릿은대문자 X 6 개로마치도록해야한다. /tmp/hanbitxxxxxx 47/51
[ 예제 2-20] 임시파일명만들기 ex2_20.c 01 #include <stdio.h> 02 #include <stdlib.h> 03 #include <string.h> 04 05 int main(void) { 06 char *fname; 07 char fntmp[bufsiz]; 08 char template[32]; 09 10 fname = tmpnam(null); # ex2_20.out 1. TMP File Name(tmpnam) : /var/tmp/aaafuagoe 2. TMP File Name(tmpnam) : /var/tmp/baaguagoe 3. TMP File Name(tempnam) : /tmp/hanbiaaahuagoe 4. TMP File Name(mktemp) : /tmp/hanbitiuagoe 11 printf("1. TMP File Name(tmpnam) : %s\n", fname); 12 13 tmpnam(fntmp); 14 printf("2. TMP File Name(tmpnam) : %s\n", fntmp); 15 16 fname = tempnam("/tmp", "hanbit"); 17 printf("3. TMP File Name(tempnam) : %s\n", fname); 18 19 strcpy(template, "/tmp/hanbitxxxxxx"); 20 fname = mktemp(template); 21 printf("4. TMP File Name(mktemp) : %s\n", fname); 22 23 return 0; 24 } 48/51
임시파일의파일포인터생성 tmpfile(3) 자동으로 w+ 모드로열린파일포인터를리턴 #include <stdio.h> FILE *tmpfile(); [ 예제 2-21] tmpfile 함수사용하기 ex2_21.c 01 #include <stdio.h> 02 03 int main(void) { 04 FILE *fp; 05 06 fp = tmpfile(); 07 08 fputs("unix system", fp); 09 10 fclose(fp); 11 12 return 0; 13 } 임시파일에출력출력 49/51
요약 파일 파일은관련있는데이터들의집합으로하드디스크같은저장장치에일정한형태로저장된다. 유닉스에서파일은데이터를저장하기위해서뿐만아니라데이터를전송하거나장치에접근하기위해서도사용한다. 저수준파일입출력과고수준파일입출력 저수준파일입출력 : 유닉스커널의시스템호출을사용하여파일입출력을실행하며, 특수파일도읽고쓸수있다. 고수준파일입출력 : 표준입출력라이브러리로다양한형태의파일입출력함수를제공한다. 50/51
IT CookBook, 유닉스시스템프로그래밍