首页 > 代码库 > readn,writen,readline

readn,writen,readline

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             else14                 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  >= 022 }

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             else14                 return -1;//error write15         }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 read17             else18                 break;//EOF, some data was read19         }else20             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             else14                 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             else18                 break;19         }else20             return -1;21     }22     *buf = \0;23     return n;24 }