RIO
- 解决short count
- 提供方便、健壮、高效的IO
两类函数
- 无缓冲的输入输出
rio_readn
rio_writen
绝不会返回不足值
- 带缓冲的输入输出
rio_readlineb
读文本行
停止条件
读了maxlen个字节
遇到了EOF
遇到了换行符
rio_readnb
读字节 不区分文本和二进制文件
停止条件
maxlen : 因为里面用了一个while循环,如果还有left,就继续读,如果buffer已经空了,就调用rio_read填充buffer后再读。
遇到EOF
readlineb和readnb可以混用,但不能和readn混用
/*my version of rio*/
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
typedef struct{
int rio_fd; //file descriptor
int rio_cnt; //unread bytes
char rio_buffer[32];
char *rio_p; //pointer to next unread byte;
} rio_t;
void rio_initb(rio_t *rp, int fd){
rp->rio_fd = fd;
rp->rio_cnt = 0;
rp->rio_p = rp->rio_buffer;
}
//把buffer里的拷贝进usrbuf
int rio_read(rio_t *rp, char *usrbuf, size_t size){
while(rp->rio_cnt <= 0){
rp->rio_cnt = read(rp->rio_fd, rp->rio_buffer, sizeof(rp->rio_buffer));
if(rp->rio_cnt < 0){
if(errno != EINTR){
return -1;
}
}else if(rp->rio_cnt == 0){
return 0;
}else{
rp->rio_p = rp->rio_buffer;
}
}
int cnt = size;
if(cnt > rp->rio_cnt){
cnt = rp->rio_cnt;
}
memcpy(usrbuf, rp->rio_p, cnt);
rp->rio_p += cnt;
rp->rio_cnt -= cnt;
return cnt;
}
int rio_readnb(rio_t *rp, char *des, size_t size){
int left = size;
int n;
char *p = des;
while(left > 0){
n = rio_read(rp, p, left);
if(n < 0){
return -1; /* errno set by read() */
}else if(n==0){
break; /* EOF */
}else{
left -= n;
p += n;
}
}
return (size - left);
}
int rio_readlineb(rio_t *rp, char* des, size_t max_size){
int left = max_size-1;
char *p = des;
int n;
while(left > 0){
if(n = rio_read(rp, p, 1) == 1){
left--;
if(*p == '\n'){
p++;
break;
}else{
p++;
}
}else if(n==0){
if(p == des) return 0; //no data read, EOF
else break; // some data read, EOF
}else{
return -1;
}
}
*p = 0;
return p-des;
}
int main()
{
rio_t rt;
int fd1 = open("README2", O_RDONLY);
rio_initb(&rt, fd1);
char buf[64];
int size = 64;
rio_readlineb(&rt, buf, size);
printf("%s", buf);
}
/****************************************
* The Rio package - Robust I/O functions
****************************************/
/*
* rio_readn - Robustly read n bytes (unbuffered)
*/
/* $begin rio_readn */
ssize_t rio_readn(int fd, void *usrbuf, size_t n)
{
size_t nleft = n;
ssize_t nread;
char *bufp = usrbuf;
while (nleft > 0)
{
if ((nread = read(fd, bufp, nleft)) < 0)
{
if (errno == EINTR) /* Interrupted by sig handler return */
nread = 0; /* and call read() again */
else
return -1; /* errno set by read() */
}
else if (nread == 0)
break; /* EOF */
nleft -= nread;
bufp += nread;
}
return (n - nleft); /* Return >= 0 */
}
/* $end rio_readn */
/*
* rio_writen - Robustly write n bytes (unbuffered)
*/
/* $begin rio_writen */
ssize_t rio_writen(int fd, void *usrbuf, size_t n)
{
size_t nleft = n;
ssize_t nwritten;
char *bufp = usrbuf;
while (nleft > 0)
{
if ((nwritten = write(fd, bufp, nleft)) <= 0)
{
if (errno == EINTR) /* Interrupted by sig handler return */
nwritten = 0; /* and call write() again */
else
return -1; /* errno set by write() */
}
nleft -= nwritten;
bufp += nwritten;
}
return n;
}
/* $end rio_writen */
/*
* rio_read - This is a wrapper for the Unix read() function that
* transfers min(n, rio_cnt) bytes from an internal buffer to a user
* buffer, where n is the number of bytes requested by the user and
* rio_cnt is the number of unread bytes in the internal buffer. On
* entry, rio_read() refills the internal buffer via a call to
* read() if the internal buffer is empty.
*/
/* $begin rio_read */
static ssize_t rio_read(rio_t *rp, char *usrbuf, size_t n)
{
int cnt;
while (rp->rio_cnt <= 0)
{ /* Refill if buf is empty */
rp->rio_cnt = read(rp->rio_fd, rp->rio_buf,
sizeof(rp->rio_buf));
if (rp->rio_cnt < 0)
{
if (errno != EINTR) /* Interrupted by sig handler return */
return -1;
}
else if (rp->rio_cnt == 0) /* EOF */
return 0;
else
rp->rio_bufptr = rp->rio_buf; /* Reset buffer ptr */
}
/* Copy min(n, rp->rio_cnt) bytes from internal buf to user buf */
cnt = n;
if (rp->rio_cnt < n)
cnt = rp->rio_cnt;
memcpy(usrbuf, rp->rio_bufptr, cnt);
rp->rio_bufptr += cnt;
rp->rio_cnt -= cnt;
return cnt;
}
/* $end rio_read */
/*
* rio_readinitb - Associate a descriptor with a read buffer and reset buffer
*/
/* $begin rio_readinitb */
void rio_readinitb(rio_t *rp, int fd)
{
rp->rio_fd = fd;
rp->rio_cnt = 0;
rp->rio_bufptr = rp->rio_buf;
}
/* $end rio_readinitb */
/*
* rio_readnb - Robustly read n bytes (buffered)
*/
/* $begin rio_readnb */
ssize_t rio_readnb(rio_t *rp, void *usrbuf, size_t n)
{
size_t nleft = n;
ssize_t nread;
char *bufp = usrbuf;
while (nleft > 0)
{
if ((nread = rio_read(rp, bufp, nleft)) < 0)
return -1; /* errno set by read() */
else if (nread == 0)
break; /* EOF */
nleft -= nread;
bufp += nread;
}
return (n - nleft); /* return >= 0 */
}
/* $end rio_readnb */
/*
* rio_readlineb - Robustly read a text line (buffered)
*/
/* $begin rio_readlineb */
ssize_t rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen)
{
int n, rc;
char c, *bufp = usrbuf;
for (n = 1; n < maxlen; n++)
{
if ((rc = rio_read(rp, &c, 1)) == 1)
{
*bufp++ = c;
if (c == '\n')
{
n++;
break;
}
}
else if (rc == 0)
{
if (n == 1)
return 0; /* EOF, no data read */
else
break; /* EOF, some data was read */
}
else
return -1; /* Error */
}
*bufp = 0;
return n - 1;
}
/* $end rio_readlineb */
下一篇:
ES使用过程中遇到的坑→