回顾C文件接口
写入文件
#include<stdio.h>
#include<string>
int main()
{
FILE *fp=fopen("myfile","w");
if(!fp){
printf("fopen error\n");
}
const char *msg="hello world\n";
int count=5;
while(count--){
fwrite(msg,strlen(msg),1,fp);
}
fclose(fp);
return 0;
}
读取文件
#include<stdio.h>
#include<string.h>
int mian()
{
FILE *fp=fopen("myfile","r");
if(!fp){
perror("fopen error");
}
char buf[1024];
const char *msg="hello world\n";
while(1){
size_t s=fread(buf,1,strlen(msg),fp);
if(s>0){
buf[s]=0;
printf("%s",buf[s]);
}
if(feof(fp)){
break;
}
}
fclose(fp);
return 0;
}
输出文件到显示屏
#include<stdio.h>
#include<string>
int main()
{
char *msg="hello wrold";
fwrite(msg,strlen(msg),1,stdout);
printf("hello printf");
fprintf(stdout,"hello fprintf");
return 0;
}
stdin&stdout&stderr
- c会默认打开这三个输入输出流。
- 这三个流的类型都是FILE*,fopen返回值类型,文件指针
小结
r:以可读方式打开
r+:以可读可写方式打开
w:以可写方式打开,清空原有内容,文件不存在则创建
w+:以可写可读方式打开,清空文件原有内容,文件不存在则创建
a:以追加写(文尾)的方式打开文件,文件不存在则创建
a+:以可读(文首)追加写(文尾)的方式打开文件,文件不存在则创建
系统文件IO
写文件
#include<stdio.h>
#include<string.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
int main()
{
umask(0);
int fd=open("file1",O_WRONLY|O_CREAT,0644);
if(fd<0){
perror("open error");
return 0;
}
int count=5;
const char *msg="hello world\n";
int len=strlen(msg);
while(count--){
write(fd,msg,len);
}
close(fd);
return 0;
}
读文件
#include<stdio.h>
#include<string.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
int main(){
umask(0);
int fd=open("file1",O_RDONLY);
if(fd<0){
perror("open error");
return 0;
}
const char *msg="hello world\n";
char buf[1024];
while(1){
int s= read(fd,buf,strlen(msg));
if(s>0){
printf("%s",buf);
}
else{
break;
}
}
close(fd);
return 0;
}
接口介绍
open
#include<sys/types.h>
#include<sys/stst.h>
int open(const char *patnname,int flags);
int open(const char *patnname,int flags,mode_t mode);
- patnname:要打开或创建的目标文件
- flags:打开文件时,可以传入的多个参数选项,用下面的一个或多个常量进行“或”运算,构成flags.
参数:
O_RDONLY:只读打开
O_WRONLY:只写打开
O_RDWR:读、写打开
前三个常量必须指定一个且只能指定一个。
O_CREAT:若文件不存在则创建,需要使用mode选项来指明新文件的访问权限。与O_EXCL连用,文件存在会报错。
O_APPEND:追加写
O_TRUNK:打开文件时清空原有内容
返回值:
成功:新打开的文件描述符
失败:-1
f#系列的函数是C标准库中的函数,称为库函数,都是对系列调用接口的封装,方便二次开发
文件描述符fd
文件描述符是内核中文件信息结构数组的下标。
也可以说fd就是open返回的一个小整数。
0&1&2
- Linux进程默认情况下会有三个缺省打开的文件描述符,分别是0(标准输入),1(标准输出),2(标准错误)。
- 0、1、2对应的物理设备一般是键盘、鼠标、显示器,所以输入输出还可以采用如下方式:
-
文件符就是从0开始的小整数,当我们打开文件时,操作系统在内存中要创建相应的数据结构来描述目标文件。于是就有了file结构体,表示一个已经打开的文件对象。
-
进程执行open进程调用,所以必须让进程和文件关联起来。每个进程都有一个指针*files,指向一张表files_struct,该表做重要的部分就是包含一个指针数组,每一个元素都是指向打开元素的指针。
-
本质上,文件描述符就是该数组的下标。所以,只要拿着文件描述符就可以找到对应的文件
重定向
本质上是对文件描述符的重定向(通过改变下标所对应的文件描述信息,而修改索要操作的文件)
#include<stdio.h>
#include<stdlib.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
int main(){
close(1);//
int fd=open("myfile",O_WRONLY|O_CREAT,0644);
if(fd<0){
perror("open");
return 1;
}
printf("fd:%d\n",fd);
fflush(stdout);
close(fd);
exit(0);
}
//运行后发现本应输出到显示器上的内容,输出到了myfile文件中。
//这种现象就叫重定向。
使用dup2系统调用
//函数原型
#include<unistd.h>
int dup2(int oldfd,int newfd);
//int dup2(3,1);将fd1中换成fd3中所描述的信息
FILE
FILE* 文件流指针
- 因为IO相关函数与系统调用接口对应,并且库函数封装系统调用,所以本质上访问文件都是通过fd访问的。
- c库当中的FILE结构内部,封装了fd。