文件相关函数
1.1 打开和关闭文件
#include<sys/type.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
/**
flag:O_RDONLY:只读
O_WRONLY:只写
O_RDWR:可读可写
p624
*/
int open(char* filename,int flag,mode_t mode);成功返回文件描述符,失败fanhui-1
int close(int fd);成功为0,失败返回-1
1.2 读写文件
#include<unistd.h>
typedef long ssize_t;
typedef
ssize_t read(int fd,void* buf,size_t n);//从fd中读取n字节的数据到内存,由buf指针指向首位置:成功返回读字节数,失败返回-1
ssize_t write(int fd,const void *buf,size_t n);//向fd中写入buf指针指向的n字节的数据:成功返回写的字节数,失败返回-1
1.3 rio健壮读写
#include <sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include <unistd.h>
#include<errno.h>
1.3.1 不带缓冲区读写
和read的区别?
参数和返回意义都相同
不同的是read和rio_readn在读取文件失败时的操作不同:
read在读取文件失败时,直接返回-1
rio_readn在读取文件失败时,如果是由于中断信号导致会一直循环尝试读取,其他错误返回-1(这对套接字很有用)
ssize_t rio_readn(int fd, void *usrbuf, size_t n)
{
size_t nleft = n;//未读字节数
ssize_t nread;
char *bufp = (char*)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 */
}
和write的区别?
参数和返回意义都相同
不同的是write和rio_writen在读取文件失败时的操作不同:
write在写文件失败时,直接返回-1
rio_writen在写文件失败时,如果是由于中断信号导致会一直循环尝试读取,其他错误返回-1
ssize_t rio_writen(int fd, void *usrbuf, size_t n)
{
size_t nleft = n;
ssize_t nwritten;
char *bufp = (char*)usrbuf;
while (nleft > 0) {
if ((nwritten = write(fd, bufp, nleft)) <= 0) {
if (errno == EINTR)
nwritten = 0;
else
return -1;
}
nleft -= nwritten;
bufp += nwritten;
}
return n;
}
1.3.2 带缓冲区的读写
缓冲区的作用?(缓存已经从文件读取的内容)
不带缓冲区是直接从磁盘读到内存;带缓冲区是从磁盘读到缓冲区(缓冲区也在内存)再读到内存
试想,如果从文件读了020字节的数据,此时当前的位置指针指向文件第21个指针,如果内存还需要读取020字节的数据呢?
没有缓冲区:修改文件当前的位置指针,重新从磁盘读(速度慢)
有缓冲区:从rio_buf中读,在内存(速度快)
/**
缓冲区的定义与初始化
*/
#define RIO_BUFSIZE 8192 //缓冲区最大字节数
typedef struct {
int rio_fd; //与内部缓冲区关联的描述符
int rio_cnt; //缓冲区中剩下的字节数
char *rio_bufptr; //指向缓冲区中下一个未读的字节
char rio_buf[RIO_BUFSIZE];
} rio_t;
void rio_readinitb(rio_t *rp, int fd)
{
rp->rio_fd = fd; //缓冲区和文件描述符绑定
rp->rio_cnt = 0; //剩下的字节数为0
rp->rio_bufptr = rp->rio_buf;
}
static ssize_t rio_read(rio_t *rp, char *usrbuf, size_t n)
{
int cnt;
while (rp->rio_cnt <= 0) { //缓冲区为空,调用read填充
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;
}
ssize_t rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen)
{
int n, rc;
char c, *bufp = (char*)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
else
break; //读了一些数据后遇到EOF
} else
return -1; /* Error */
}
*bufp = 0;
return n-1;
}
ssize_t rio_readnb(rio_t *rp, void *usrbuf, size_t n)
{
size_t nleft = n;
ssize_t nread;
char *bufp = (char*)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 */
}
1.4 读取文件信息
#include<unistd.h>
#include<sys/stat.h>
struct stat
{
dev_t st_dev; /* ID of device containing file -文件所在设备的ID*/
ino_t st_ino; /* inode number -inode节点号*/
mode_t st_mode; /* protection -保护模式?*/
nlink_t st_nlink; /* number of hard links -链向此文件的连接数(硬连接)*/
uid_t st_uid; /* user ID of owner -user id*/
gid_t st_gid; /* group ID of owner - group id*/
dev_t st_rdev; /* device ID (if special file) -设备号,针对设备文件*/
off_t st_size; /* total size, in bytes -文件大小,字节为单位*/
blksize_t st_blksize; /* blocksize for filesystem I/O -系统块的大小*/
blkcnt_t st_blocks; /* number of blocks allocated -文件所占块数*/
time_t st_atime; /* time of last access -最近存取时间*/
time_t st_mtime; /* time of last modification -最近修改时间*/
time_t st_ctime; /* time of last status change - */
};
int stat(const char*filename,struct stat*buf);//读取文件的信息,放入buf中,成功返回0,失败返回-1
int fstat(int fd,struct stat* buf);//读取文件的信息,放入buf中,成功返回0,失败返回-1
1.5 I/O重定向
#include<unistd.h>
int dup2(int old,int newfd);//让newfd描述符指向old描述符所指向的打开文件表,成功返回非负描述符,失败返回-1