Linux 基础文件IO操作
Ⅰ、理解文件
一、什么是文件?
一个文件里边没有任何数据那么这个文件的大小是0KB吗?答案是:不是的他还有他的属性,换一句话来说 文件 = 内容 + 属性 。所以我们对文件的操作可以大概分为两种一个是对文件内容的操作和文件的属性操作。
二、从系统的角度理解文件操作
操作系统是硬件的管理者,文件是存储在外存中的,我们是无法直接和硬件去进行操作的所以我们的所有操作都要操作系统去帮我们完成因为OS是一款管理软硬件的一款软件,那么操作系统要完成一个任务要创建进程,从这里我们可以推导出我们对于文件的操作最后变成了进程对于文件的操作,我们想一个问题那么一个进程只能打开一个文件吗?这个答案也是不会,因为OS会默认给我们打开标准输入流,标准输出流,标准错误流,所以 进程:文件是1:n 的关系。那么一个进程可以打开这么多文件如何去管理呢?答案是和进程一样 先描述,再组织 ,先创建一个结构体把数据进行描述再用某种数据结构去管理这些结构体节点。这个结构体就是struct_file。
下面这幅图展示了进程task_struct 和 struct file 的关系:
Ⅱ、文件操作
一、C语言文件操作
1、文件打开
fopen:
fopen的第一个参数是文件的路径和文件名,路径包含绝对路径和相对路径,当没有带路径的时候会在当前路径下寻找,为什么再当前路径下寻找?在fopen函数内判断是否携带路径如果,没有带函数会获取环境变量PATH当作路径加到文件名前面。第二个参数是想什么方式去访问文件?有w,w+,a,a+,r,r+等等,下面我们将看一张图清楚的理解这几种方式的区别。
如果打开失败fopen会返回NULL,如果成功会返回这个文件的文件指针。
2、文件写入
fprintf:
fprintf可以按照指定的格式向文件里写入数据,如果成功会返回写入字符的个数,失败则会返回一个负值。
#include<stdio.h>2 3 int main()4 {5 FILE* fd = fopen("log.txt","w");6 if(fd == NULL)7 {8 perror("fopen:");9 return 1;10 }11 int ret = fprintf(fd,"这是一个日志文件!\n"); 12 if(ret < 0)13 {14 perror("fpritf:");15 return 2;16 }17 18 return 0;19 }
snprintf:
snprintf 的第一个参数是写入的目标字符串地址,第二个参数是目标字符串的大小,后面的参数是可变参数和 printf 一样填。
成功的话返回写入字符的个数,失败的话返回一个负数。
#include<stdio.h>2 #include<string.h> 3 #define FILENAME "log.txt"4 #define BUFFERSIZE 325 int main()6 {7 FILE* fd = fopen(FILENAME,"w");8 if(fd == NULL)9 {10 perror("fopen:");11 return 1;12 }13 14 char buffer[BUFFERSIZE];15 memset(buffer,0,sizeof(buffer));16 snprintf(buffer,sizeof(buffer),"This is a log file\n");17 fprintf(fd,"%s",buffer);18 19 return 0;20 }
3、 文件读取
fgets:
fgets的第一个参数是目标字符串地址,第二个参数是目标字符串大小,第三个参数是文件指针。
如果读取成功会返回char* str,当遇到文件结尾EOF且没有读到任何数据的时候会返回NULL。
#include<stdio.h>2 #include<string.h>3 #define FILENAME "log.txt"4 #define SIZE 645 6 int main()7 {8 FILE* fd = fopen(FILENAME,"r");9 if(fd == NULL)10 {11 perror("fopen : ");12 return 1;13 }14 15 char buffer[SIZE];16 fgets(buffer,sizeof(buffer),fd);17 printf("%s",buffer);18 return 0; 19 }
4、文件关闭
fclose:
fclose的参数是要关闭的文件指针,当函数成功的时候就会返回0,当失败的时候会返回EOF(-1)。
二、系统调用文件操作
1、open
我们看到这两个open函数是经过封装过一层的,他们的底层都是调用同一个open函数的,这个open函数参数是可变参数。
open函数的第一个参数是路径和文件名字符串的指针,第二个参数是打开的方式,第三个参数是如果要创建新文件,新文件的权限(权限受umask的影响)。
下面我们来解释一下第二个参数如何传参?
先解释一下如果遇到多个标记位如何去传参。先看一段代码:
1#include<stdio.h>2 #include<string.h>3 4 #define ONE_FLAG (1<<0)5 #define TWO_FLAG (1<<1)6 #define THREE_FLAG (1<<2) 7 8 int main()9 {10 int num = 0;11 scanf("%d",&num);12 if(num & ONE_FLAG)13 {14 printf(" 1 \n");15 }16 if(num & TWO_FLAG)17 {18 printf(" 2 \n");19 }20 if(num & THREE_FLAG)21 {22 printf(" 3 \n");23 }24 return 0;25 }
当TWO_FLAG和其他的数字与的时候都是0,只有和第二位是1的数字与的时候才为1
通过多个标志位或的方式可以一个参数可以传多个标志位。看下面代码:
1 #include<stdio.h>2 #include<string.h>3 4 #define ONE_FLAG (1<<0)5 #define TWO_FLAG (1<<1)6 #define THREE_FLAG (1<<2)7 8 void Print(int num)9 {10 if(num & ONE_FLAG)11 {12 printf("ONE_FLAG\n");13 }14 if(num & TWO_FLAG) 15 {16 printf("TWO_FLAG\n");17 }18 if(num & THREE_FLAG)19 {20 printf("THREE_FLAG\n");21 }22 23 return ;24 }25 26 int main()27 {28 Print(ONE_FLAG | THREE_FLAG);29 return 0;30 31 }
~
下面来看open第二个参数的常用的类型:
- O_RDONLY:只读
- O_WRONLY:只写
- O_RDWR:读写
- O_TRUNC:若文件存在且为可写模式,将其长度截断为 0(清空内容)
- O_APPEND:每次写操作都追加到文件末尾(自动移动文件指针)
2、write
write的第一个参数是文件描述符,第二个参数是缓冲区的数据,第三个参数是要输入字符的大小
如果成功会返回成功写入的字节数,如果失败会返回-1。
3、close
如果成功会返回0,失败的话会返回-1.
Ⅲ、总结
我们从文件是什么?文件操作本质是什么?开始说起,分析了C语言和系统调用常用的一些文件操作,我们在最后在想一个问题:文件操作是C语言独有的吗?这个答案肯定不是的,C++,Java,等语言中都有,他们都是把这些系统级调用进行封装用来面对上层不同的需求,也为了更好的实现跨平台。
=========================================================================
本篇关于Linux的文件理解与操作的介绍就暂告段落啦,希望能对大家的学习产生帮助,欢迎各位佬前来支持纠正!!!