九、文件IO——案例构建标准库
例子如下:
mystdio.h
1 #ifndef __MYSTDIO_H__ 2 #define __MYSTDIO_H__ 3 4 #include <sys/types.h> 5 6 #define MYEOF -1 7 8 enum mode{READ, WRITE, APPEND}; 9 10 typedef struct { 11 int _fd; 12 char *_buff; 13 char *_nextc; 14 int _mode; 15 off_t _left; 16 }MYFILE; 17 18 extern MYFILE * myfopen(const char * const pathname, const char * const mode); 19 20 extern int myfclose(MYFILE *fp); 21 22 extern void myfflush(MYFILE *fp); 23 24 extern MYFILE* myfdopen(int fd, const char * const mode); 25 26 extern int myfgetc(MYFILE *fp); 27 28 extern int myfputc(int character, MYFILE *fp); 29 30 #endif
mystdio.c
1 #include "mystdio.h" 2 #include <sys/types.h> 3 #include <sys/stat.h> 4 #include <fcntl.h> 5 #include <unistd.h> 6 #include <string.h> 7 #include <errno.h> 8 #include <stdlib.h> 9 #include <stdio.h> 10 #include <fcntl.h> 11 #include <assert.h> 12 #include <malloc.h> 13 #include <memory.h> 14 15 #define BUFFER_LEN 4096 16 17 MYFILE * myfopen(const char * const pathname, const char * const mode) 18 { 19 int fd; 20 if(!strcmp(mode, "r")) { 21 fd = open(pathname, O_RDONLY); 22 } else if(!strcmp(mode, "w")) { 23 fd = open(pathname, O_WRONLY | O_CREAT | O_TRUNC, 0777); 24 } else if(!strcmp(mode, "a")) { 25 fd = open(pathname, O_WRONLY | O_CREAT | O_APPEND, 0777); 26 } else { 27 return NULL; 28 } 29 30 if(fd < 0) 31 return NULL; 32 33 return myfdopen(fd, mode); 34 } 35 36 int myfclose(MYFILE *fp) 37 { 38 myfflush(fp); 39 int ret = close(fp->_fd); 40 free(fp->_buff); 41 free(fp); 42 return ret; 43 } 44 45 void myfflush(MYFILE *fp) 46 { 47 if(fp->_mode == READ) { 48 fp->_nextc = fp->_buff;//指向缓存开始地址 49 fp->_left = 0; 50 } else {// write or append 51 write(fp->_fd, fp->_buff,(BUFFER_LEN - fp->_left)); 52 fp->_nextc = fp->_buff; 53 fp->_left = BUFFER_LEN; 54 } 55 } 56 57 MYFILE* myfdopen(int fd, const char * const mode) 58 { 59 MYFILE *fp = (MYFILE *)malloc(sizeof(MYFILE));//堆中创建fp 60 assert(fp != NULL);//断言,即保证fp不能为空,为空就在这里跳出 61 62 fp->_buff = (char *)malloc(BUFFER_LEN); 63 assert(fp->_buff != NULL); 64 fp->_fd = fd; 65 fp->_nextc = fp->_buff;//nextc 指向缓存中第一个字节 66 if(!strcmp(mode, "r")) { 67 fp->_mode = READ; 68 fp->_left = 0;//缓存没有任何数据可读 69 } 70 71 if(!strcmp(mode, "w")) { 72 fp->_mode = WRITE; 73 fp->_left = BUFFER_LEN;//缓存的大小长度 74 } 75 76 if(!strcmp(mode, "w")) { 77 fp->_mode = APPEND; 78 fp->_left = BUFFER_LEN; 79 } 80 81 return fp; 82 } 83 84 int myfgetc(MYFILE *fp) 85 { 86 assert(fp->_mode == READ); 87 88 //当缓存中的数据已经读取完毕,再从文件中读取一批新的数据放入到缓存当中 89 if(fp->_left == 0) { 90 ssize_t size = read(fp->_fd, fp->_buff, BUFFER_LEN); 91 assert(size >= 0); 92 if(size == 0) return MYEOF; 93 fp->_nextc = fp->_buff; 94 fp->_left = size; 95 } 96 97 char c = *(fp->_nextc); 98 fp->_nextc++; 99 fp->_left--; 100 101 return c; 102 } 103 104 int myfputc(int character, MYFILE *fp) 105 { 106 assert(fp->_mode == WRITE || fp->_mode == APPEND); 107 108 //若缓存满,将缓存中的数据写入到文件中 109 if(fp->_left == 0) { 110 if(write(fp->_fd, fp->_buff, BUFFER_LEN) != BUFFER_LEN) { 111 return 0; 112 } 113 114 fp->_nextc = fp->_buff; 115 fp->_left = BUFFER_LEN; 116 } 117 118 // 将字符写入到缓存制定的位置 119 *(fp->_nextc) = (char)character; 120 fp->_nextc++; 121 fp->_left--; 122 123 return 1; 124 }
mystdio_test.c
1 #include <sys/types.h> 2 #include <sys/stat.h> 3 #include <fcntl.h> 4 #include <unistd.h> 5 #include <string.h> 6 #include <errno.h> 7 #include <stdlib.h> 8 #include <stdio.h> 9 #include <fcntl.h> 10 #include <assert.h> 11 #include "mystdio.h" 12 13 int main(int argc, const char *argv[]) 14 { 15 MYFILE *fp1 = myfopen("/etc/passwd", "r"); 16 assert(fp1 != NULL); 17 MYFILE *fp2 = myfopen("mypasswd", "w"); 18 assert(fp2 != NULL); 19 20 char c; 21 while((c = myfgetc(fp1)) != MYEOF) 22 { 23 myfputc(c, fp2); 24 } 25 26 myfclose(fp1); 27 myfclose(fp2); 28 return 0; 29 }
编译调试: