1.当一个程序运行后,系统会默认打开三个文件描述符: 0、1、2(stdin、stdout、stderr);
#include<my_head.h>
int main(int argc, const char *argv[])
{
printf("stdin的文件描述符:%d\n",stdin->_fileno);
printf("stdout的文件描述符:%d\n",stdout->_fileno);
printf("stderr的文件描述符:%d\n",stderr->_fileno);
return 0;
}
![](https://img-blog.csdnimg.cn/4eeae221c97c4e40807afce989cac81f.png)
2.open函数以只写的方式打开文件,给予文件权限0666,并关闭文件(close);
#include<my_head.h>
int main(int argc, const char *argv[])
{
int fd; //定义文件描述符
//以只写方式打开文件
if((fd=open("./c.txt",O_WRONLY|O_CREAT,0666)) == -1)
{
perror("open error");
return -1;
}
//关闭文件
if(close(fd) == -1)
printf("文件关闭失败\n");
else
printf("文件关闭成功\n");
return 0;
}
![](https://img-blog.csdnimg.cn/bb6e4e00cfa94bc38399305907feef25.png)
3.使用O_EXCL创建文件,判断文件是否已经存在,如果打开文件时,文件已经存在,则open函数会返回一个EEXIST;
#include<my_head.h>
int main(int argc, const char *argv[])
{
int fd; //文件描述符
if((fd=open("./c.txt",O_RDWR|O_CREAT|O_EXCL,0664)) == -1) //打开文件
{
if(errno == EEXIST) //若文件存在,将错误码置EEXIST
{
printf("文件已存在,无需重复创建\n");
fd = open("./c.txt",O_RDONLY);
}else
{
perror("open error");
return -1;
}
}
return 0;
}
![](https://img-blog.csdnimg.cn/e504c05d163040879d1d3eeeac468688.png)
4.向指定文件写入fd写入数据(write),然后读取数据(read),最后把数据写到标准输出文件描述符中(write);
#include<my_head.h>
int main(int argc, const char *argv[])
{
int fd; //文件描述符
//只写打开文件
if((fd=open("./b.txt",O_WRONLY|O_CREAT|O_TRUNC,0664)) == -1)
{
perror("open error");
return -1;
}
printf("fd=%d\n",fd); //输出文件描述符
char buf[128] = "hello! how are you?";
write(fd,buf,sizeof(buf)); //向文件中写入数据
close(fd); //关闭文件
//只读方式打开文件
if((fd=open("./b.txt",O_RDONLY)) == -1)
{
perror("open error");
return -1;
}
char buf1[36];
int ret = read(fd,buf1,sizeof(buf1)); //从文件中读取数据放到buf1中
write(1,buf1,ret); //将数据写入到标准输出文件描述符中
puts("");
close(fd); //关闭文件
return 0;
}
![](https://img-blog.csdnimg.cn/92e5f904859b48e2a327b9b6dc9cec15.png)
5. 使用read、write函数完成两个文件的拷贝;
#include<my_head.h>
int main(int argc, const char *argv[])
{
int srcfd,tarfd; //文件描述符
if(argc != 3) //判读输入文件个数
{
puts("input file error");
return -1;
}
//只读打开srcfd
if((srcfd=open(argv[1],O_RDONLY)) == -1)
{
perror("srcfd open error");
return -1;
}
//只写打开tarfd
if((tarfd=open(argv[2],O_WRONLY|O_CREAT|O_TRUNC,0664)) == -1)
{
perror("tarfd open error");
return -1;
}
char buf[128] = "";
int ret; //记录每次读取的字符个数
//文件拷贝
while((ret = read(srcfd,buf,sizeof(buf))) != -1 && ret != 0)
{
write(tarfd,buf,ret);
}
close(srcfd); //关闭文件
close(tarfd);
puts("拷贝成功");
return 0;
}
![](https://img-blog.csdnimg.cn/7b6ece7b23034c4d95851f0614ef09e6.png)
6.利用lseek函数得到文件的大小;
#include<my_head.h>
int main(int argc, const char *argv[])
{
int fd; //文件描述符
//只读打开文件
if((fd=open("./b.txt",O_RDONLY)) == -1)
{
perror("open error");
return -1;
}
printf("文件的大小:%ld\n",lseek(fd,0,SEEK_END)); //lseek函数
close(fd);
return 0;
}
![](https://img-blog.csdnimg.cn/9aaf8afc1dfa48869141c8200e72b9f5.png)
7.利用lseek函数得到图片的大小;
#include<my_head.h>
int main(int argc, const char *argv[])
{
int fd; //文件描述符
//只读打开图片
if((fd=open("../day2/lyy.bmp",O_RDONLY)) == -1)
{
perror("open error");
return -1;
}
//获取文件头部分的文件大小
lseek(fd,2,SEEK_SET);
//读取图片的大小
int img_size;
read(fd,&img_size,sizeof(img_size));
printf("图片的大小:%d\n",img_size);
close(fd); //关闭文件
return 0;
}
![](https://img-blog.csdnimg.cn/0b3e102a5aa14f52bb012cecfd18b853.png)
8.关于文件描述符拷贝问题
8.1文件描述符的直接拷贝(fd2=fd1),该过程,没有产生新的文件描述符,两个变量共同使用同一个光标;
#include<my_head.h>
int main(int argc, const char *argv[])
{
//打开并打印fd1文件描述符
int fd1;
if((fd1=open("./d.txt",O_RDWR|O_CREAT|O_TRUNC,0664)) == -1)
{
perror("open error");
return -1;
}
printf("fd1=%d\n",fd1);
int fd2 = fd1; //直接拷贝文件描述符
//通过fd1向文件中写入数据
write(fd1,"hi how are you",strlen("hi how are you"));
//buf存放fd2读取的数据,如果能读出数据,说明不共享光标
//如果不能读出数据,说明共享光标
char buf[6] = "";
read(fd2,buf,sizeof(buf));
write(1,buf,sizeof(buf)); //将数据写入到终端
if(close(fd1) != 0)
{
perror("close fd1 errro");
return -1;
}
if(close(fd2) != 0) //会报错,因为没有生成fd2文件描述符
{
perror("close fd2 errro");
return -1;
}
return 0;
}
![](https://img-blog.csdnimg.cn/89cb70b1bd0841fbac75802bcdfbecef.png)
8.2使用dup函数进行文件描述符的拷贝,该过程,产生新的文件描述符,两个变量共同使用同一个光标;
#include<my_head.h>
int main(int argc, const char *argv[])
{
//定义文件描述符
int fd1,fd2;
//只读打开fd1
if((fd1=open("./b.txt",O_RDONLY)) == -1)
{
perror("open error");
return -1;
}
printf("fd1=%d\n",fd1);
fd2 = dup(fd1); //调用文件描述符拷贝函数
printf("fd2=%d\n",fd2);
lseek(fd1,6,SEEK_SET); //通过fd1将光标移动第6个字节处
if(close(fd1) != 0) //关闭fd1
{
perror("close fd1 errro");
return -1;
}
//buf存放fd2读取的数据,如果读出数据hello,说明不共享光标
//如果读出数据world,说明共享光标
char buf[5];
int ret = read(fd2,buf,sizeof(buf));
write(1,buf,ret); //将数据写入到标准输出中
puts("");
if(close(fd2) != 0)
{
perror("close fd2 errro");
return -1;
}
return 0;
}
![](https://img-blog.csdnimg.cn/69de92e2d2d047a58e2adaf46d757cf9.png)
8.3多次使用open函数打开同一个文件,每次使用open函数,都会产生一个新的文件描述符,该过程,产生新的文件描述符,两个变量不共同使用同一个光标;
#include<my_head.h>
int main(int argc, const char *argv[])
{
//定义文件描述符
int fd1,fd2;
//只读打开fd1
if((fd1=open("./b.txt",O_RDONLY)) == -1)
{
perror("open error");
return -1;
}
//只读打开fd1, fd1,fd2打开同一个文件
if((fd2=open("./b.txt",O_RDONLY)) == -1)
{
perror("open error");
return -1;
}
printf("fd1=%d\n",fd1);
printf("fd2=%d\n",fd2);
lseek(fd1,6,SEEK_SET); //通过fd1将光标移动第6个字节处
//buf存放fd2读取的数据,如果读出数据hello,说明不共享光标
//如果读出数据world,说明共享光标
char buf[5];
int ret = read(fd2,buf,sizeof(buf));
write(1,buf,ret); //将数据写入到标准输出中
puts("");
close(fd1);
close(fd2);
return 0;
}
![](https://img-blog.csdnimg.cn/5ec05aa657b8434bb2a903870b55dc32.png)
8.4使用dup2函数完成文件描述符的拷贝,该过程,产生新的文件描述符,两个变量共同使用同一个光标;
#include<my_head.h>
int main(int argc, const char *argv[])
{
//定义文件描述符
int fd1,fd2;
//只读打开fd1
if((fd1=open("./c.txt",O_RDONLY)) == -1)
{
perror("open error");
return -1;
}
//读写打开fd2
if((fd2=open("./b.txt",O_RDONLY)) == -1)
{
perror("open error");
return -1;
}
printf("fd1=%d\n",fd1);
printf("fd2=%d\n",fd2);
//操作结束后,fd1和fd2都指向fd2原本指向的文件
dup2(fd2,fd1);
printf("fd1=%d\n",fd1);
printf("fd2=%d\n",fd2);
lseek(fd1,6,SEEK_SET); //通过fd1将光标移动第6个字节处
//buf存放fd2读取的数据,如果读出数据hello,说明不共享光标
//如果读出数据world,说明共享光标
char buf[5];
int ret = read(fd2,buf,sizeof(buf));
write(1,buf,ret); //将数据写入到标准输出中
puts("");
close(fd1);
close(fd2);
return 0;
}
![](https://img-blog.csdnimg.cn/a1536de3ebe946d3886300230b0208de.png)
9.使用dup2函数,将stdout改为日志文件;
#include<my_head.h>
int main(int argc, const char *argv[])
{
//定义文件描述符
int fd1;
//读写打开fd1
if((fd1=open("./b.txt",O_RDWR)) == -1)
{
perror("open error");
return -1;
}
printf("fd1=%d\n",fd1);
dup2(fd1,1); //将stdou改为日志文件
printf("李白\n");
printf("苏轼\n");
printf("杜甫\n");
close(fd1);
return 0;
}
![](https://img-blog.csdnimg.cn/ce0fdd49f7c14bf9902019666e7426d1.png)
10.使用stat 函数获取文件状态;
#include<my_head.h>
int main(int argc, const char *argv[])
{
struct stat sb; //文件状态的变量
stat("b.txt",&sb); //调用文件状态函数,获取文件状态
printf("inode:%ld\n",sb.st_ino); //文件的iNode号
printf("type:%#o\n",sb.st_mode&S_IFMT); //文件的类型
printf("mode:%#o\n",sb.st_mode&0777); //文件的权限
return 0;
}
![](https://img-blog.csdnimg.cn/3079312b61c64f329788ea4f1eee2380.png)