unix的RIO提供的readn,writen,readline两类不同的函数:
1.无缓冲区的输入输出函数
rio_readn
1 ssize_t rio_readn(int fp, void *usrbuf, size_t n) 2 { 3 size_t nleft = n; 4 ssize_t nread; 5 char *bufp = usrbuf; 6 7 while(nleft > 0)//未读取一定数目的继续读,直到读取满足数目的字节 8 { 9 if((nread = read(fd, bufp, nleft)) < 0) 10 { 11 if(errno == EINTR) 12 nread = 0;//继续重新读 13 else 14 return -1;/*error read*/ 15 } 16 else if(nread == 0) 17 break; /*EOF*/ 18 nleft -= nread; 19 bufp += nread; 20 } 21 return (n - nleft);//return >= 0 22 }
rio_writen
1 ssize_t rio_writen(int fd, char *usrbuf, size_t n) 2 { 3 size_t nleft = n; 4 ssize_t nwritten; 5 char *bufp = usrbuf; 6 7 while(nleft > 0) 8 { 9 if((nwritten = write(fd, bufp, nleft)) <= 0) 10 { 11 if(errno == EINTR) 12 nwritten = 0; 13 else 14 return -1;//error write 15 } 16 nleft -= nwritten; 17 bufp += nwritten; 18 } 19 return n; 20 }
rio_readline
1 ssize_t rio_readline(int fp, void *usrbuf, size_t maxlen) 2 { 3 char c, *buf = usrbuf; 4 int n, cnt; 5 6 for(n = 1; n < maxlen; n++) 7 {//每次读取一个字符并判断,最后加个‘\0‘,实现字符串的输出 8 if((cnt = read(rp, &c, 1)) == 1) 9 { 10 *buf++ = c; 11 if(c == ‘\n‘)//找到一行末尾,退出 12 break; 13 }else if(cnt == 0) 14 { 15 if(n == 1) 16 return 0;//EOF, no data read 17 else 18 break;//EOF, some data was read 19 }else 20 return -1; 21 } 22 *buf = ‘\0‘; 23 return n; 24 }
2.带缓冲区的输入函数
核心:定义了一个含有字符数组的结构体
1 #define MAXLINE 1024 2 #define RIO_BUFFER 8192 3 typedef struct 4 { 5 int fd_; 6 int left_; 7 char *bufptr_; 8 char buff_[RIO_BUFFER]; 9 }rio_t; 10 11 void rio_init(rio_t *rp, int fd) 12 { 13 rp->fd_ = fd; 14 rp->left_ = 0; 15 rp->bufptr_ = rp->buff_; 16 }//初始化结构体
rio_read 函数功能:调用rio_read读n个字节时,读缓冲区内有rp->left_个字节,缓冲区为空,会通过read再填满缓冲区,缓冲区非空,rio_read从缓冲区拷贝n和
rp->left_ 中较小值个字节到用户缓冲区(usrbuf)中,并且返回拷贝的字节数
1 ssize_t rio_read(rio_t *rp, char *usrbuf, size_t n) 2 { 3 ssize_t nread; 4 while(rp->left_ <= 0)//缓冲区中没有内容时从文件中读, 5 { 6 nread = read(rp->fd_, rp->bufptr_, sizeof(rp->buff_)); 7 if(nread == -1) 8 { 9 if(errno == EINTR) 10 continue; 11 return -1; 12 }else if(nread == 0) 13 return 0; 14 rp->left_ = nread; 15 rp->bufptr_ = rp->buff_;//重置指针 16 } 17 18 int cnt = n; 19 if(rp->left_ < n) 20 cnt = rp->left_;//取两者较小值 21 memcpy(usrbuf, rp->bufptr_, cnt);//从缓冲区中读内容到传进来的字符指针中 22 rp->left_ -= cnt;//剩余缓冲区大小和指针都要变化 23 rp->bufptr_ += cnt; 24 return cnt; 25 }
rio_readnb 从结构体中读取n个字节,与无缓冲区的不同就是此时是从rio结构体的缓冲区中读取而不是直接从内核读取
1 ssize_t rio_readn(rio_t *rp, void *usrbuf, size_t n) 2 { 3 size_t nleft = n; 4 ssize_t nread; 5 char *bufp = usrbuf; 6 7 while(nleft > 0)//未读取一定数目的继续读,直到读取满足数目的字节 8 { 9 if((nread = rio_read(rp, bufp, nleft)) < 0) 10 { 11 if(errno == EINTR) 12 nread = 0;//继续重新读 13 else 14 return -1; 15 } 16 else if(nread == 0) 17 break; 18 nleft -= nread; 19 bufp += nread; 20 } 21 return (n - nleft); 22 }
rio_readlineb
1 ssize_t rio_readline(rio_t *rp, void *usrbuf, size_t maxlen) 2 { 3 char c, *buf = usrbuf; 4 int n, cnt; 5 6 for(n = 1; n < maxlen; n++) 7 {//每次读取一个字符并判断,最后加个‘\0‘,实现字符串的输出 8 if((cnt = rio_read(rp, &c, 1)) == 1) 9 { 10 *buf++ = c; 11 if(c == ‘\n‘)//找到一行末尾,退出 12 break; 13 }else if(cnt == 0) 14 { 15 if(n == 1) 16 return 0; 17 else 18 break; 19 }else 20 return -1; 21 } 22 *buf = ‘\0‘; 23 return n; 24 }
readn,writen,readline,布布扣,bubuko.com
时间: 2024-10-10 16:28:18