💘作者:泠沫
💘博客主页:泠沫的博客
💘专栏:初学Linux,文件认识与理解
💘觉得博主写的不错的话,希望大家三连(✌关注,✌点赞,✌评论),多多支持一下!!
目录
🏠C语言文件的相关操作
这里仅仅是对C语言文件操作函数的一些简单回顾,重点在于跟后面的系统调用接口做对比,对于这些函数内部细节不做讨论。
🚀 fopen()函数, fclose()函数
下面是fopen函数的介绍:
该函数的作用是以某种方式打开文件。
- 参数:第一个参数path表示文件名(文件名用字符串表示),第二个参数mode表示以何种方式打开文件,主要选项有"r", " r+ " , " w" , " w+ " , " a " , " a+ "。
- 参数中"r"表示只读,"w"表示只写,"r+"和"w+"表示读和写,前者如果文件不存在就报错,后者则创建。"a"和"a+"表示追加,前者如果文件不存在就报错,后者则创建。注意:其中以"w"写的方式打开文件,fopen()函数会把文件原来的内容进行清空!
- 返回值:如果打开文件成功,则返回一个该文件的FILE指针,如果打开失败,则返回NULL且错误码被设置。
下面是fclose函数的介绍:
该函数的作用是关闭已经打开的文件。
- 参数:fp表示需要关闭的文件的FILE指针。
- 返回值:关闭成功返回0,失败则错误码被设置。
🚀 fwrite()函数, fread()函数, fflush()函数
下面是fwrite函数的介绍:
该函数的作用是向已经打开文件的文件中写入数据。
- 参数:第一个参数ptr表示要写入的数据,第二个参数size表示写入的数据的每个元素的大小,第三个参数表示写入数据的元素的个数,第四个参数表示要写入的文件的FILE指针。
- 返回值:写入成功返回写入数据的个数,写入失败返回0且错误码被设置。
下面是fread函数的介绍:
该函数的作用是向已经打开的文件中读取数据。
- 参数:第一个参数ptr表示读出的数据存放该指针所指向的地址,第二个参数size表示读出的数据的每个元素的大小,第三个参数表示读出数据的元素的个数,第四个参数表示要读出的文件的FILE指针。
- 返回值:读取成功返回读出数据的个数,读取失败返回0且错误码被设置。
下面是fflush函数的介绍:
该函数的作用是刷新缓冲区(关于缓冲区,后面会进行详细的介绍)。
- 参数:stream要刷新的流,这里一般都是stdout(标准输出,也就是显示器)。
- 返回值:刷新成功返回0,刷新失败返回EOF且错误码被设置。
🚀 stdin & stdout & stderr 三个默认打开的流
stdin:标准输入,也就是键盘。
stdout:标准输出,也就是显示器。
stderr:标准错误,也就是显示器。
系统总是默认打开这三个流。
🚀 代码展示
FILE *fp = fopen("log.txt", "r");
if (fp == NULL)
{
perror("fopen");
return 1;
}
// C语言读文件
char buffer[64];
fread(buffer, sizeof(buffer[0]), sizeof buffer - 1, fp);
buffer[strlen(buffer) - 1] = '\0';
puts(buffer);
// FILE *fp = fopen(FILE_NAME, "w");
// C语言写文件
const char* mesg="hello linux";
fwrite(mesg,sizeof(mesg[0]),strlen(mesg),fp);
fclose(fp);
🏠 标记位传参
这里的标记位中的位指的是二进制位
🚀 标记位参数介绍
首先我们用整形int定义一些变量a,b,c,d,e…我们很清楚的知道,一个int类型对应的大小是4个字节,也就是32个比特位。如果我们让a=1,b=2,c=4,d=8,e=16…显然,我们可以看到,这些变量的32个比特位中只有一个比特位是1,如果我们将这些变量进行按位与(&)操作,当且仅当这些变量与自身数值相等的数字按位与结果才为真。
如果你对此还不理解,可以先看一下下面的代码来帮助你理解:
#define ONE 1
#define TWO 2
#define THREE 4
#define FOUR 8
void fun(int flag)
{
if (flag & ONE) printf("one\n");
if (flag & TWO) printf("two\n");
if (flag & THREE) printf("three\n");
if (flag & FOUR) printf("four\n");
}
int main()
{
fun(ONE);
fun(ONE | TWO | THREE | FOUR);
return 0;
}
我们观察fun()函数,我们发现fun()函数只有一个参数。
第一个fun函数被调用的时候传递到参数是ONE,最后打印结果就只是:one
但是第二个fun函数被调用的时候传递的参数是ONE | TWO | THREE | FOUR,这本质上还是一个参数,但是这个参数是由4个标记位按位或得到的最终结果,那么这个参数相当于结合了原来的4个参数的特性(4个比特位被标记为1),所以这个参数在fun()函数内部的所有if判断语句都成立,最终4个打印语句都将执行。这就是标记位传参。
🚀 标记为传参的意义
在认识到了什么是标记位传参之后,可能有人会很疑惑,这有什么用呢?
但是,如果你仔细观察,认真思考就会发现,标记位传参,最后传递的是一个参数,但是这个参数可以由多个不同的参数进行按位或操作最终得出,那么这个参数也就好似拥有也多个参数的特性。这个参数在函数内部可能就会由于比特位的特殊性,满足不同的条件,进而执行不同的代码。这就相当于实现了用一个参数代替多个参数进行传参
🏠Linux系统底层文件操作接口
这里仅仅是简单介绍open,close,write,read接口函数的作用,对于这些接口函数的返回值和某些参数暂不做详细介绍,后面在文件描述那里会有重点讲解。
🚀 open()接口, close()接口
下面是open接口函数的介绍:
该接口函数的作用是打开文件。
- 参数:第一个参数pathname表示表示要打开的文件名称,第三个参数mode是如果文件不存在,则要传递默认起始权限(最终权限受umask影响),第二个参数flags就是要用到上面笔者提前铺垫的标记位参数了。flags可以由以下参数按位异或得到:O_RDONLY,O_WRONLY,O_RDWR,O_CREAT,O_TRUNC,O_APPEND…
- O_RDONLY表示读,O_WRONLY表示写,O_RDWR表示读写,O_CREAT表示创建,O_TRUNC表示清空,O_APPEND表示追加。
下面是close接口函数的介绍:
该函数的作用是关闭文件,这里的参数fd是文件描述符(用来标识文件),在后续会有详细介绍。
🚀 write()接口, read()接口
下面是write接口函数的介绍:
该接口函数的作用是往文件里写东西。
- 参数:第一个参数fd是文件描述符,第二个参数是写入的数据指针,第三个参数是写入数据元素个数
- 这个接口函数的使用跟上面的open函数息息相关。这个接口函数要使用,open的第二个参数flags起码得是O_WRONLY,当然flags也可以按位或上O_CREAT | O_TRUNC 后者 O_TRUNC…
- 返回值:写入成功返回写入数据的个数,写入失败返回-1且错误码被设置。
下面是read接口函数的介绍:
该函数的作用是向文件中读数据。
- 参数:第一个参数表示要读出的文件的文件描述符,第二个参数buf表示读出的数据存放该指针所指向的地址,第三个参数count表示读出的数据的每个元素的大小。
- 返回值:读取成功返回读出数据的个数,读取失败返回-1且错误码被设置。
🚀 代码展示
// 系统调用读文件
int fd = open("log.txt", O_RDONLY);
if (fd < 0)
{
perror("open: ");
return 1;
}
char buffer[1024];
ssize_t size = read(fd, buffer, sizeof(buffer) - 1);
if (size > 0) buffer[size] = '\0';
printf("%s", buffer);
// 系统调用写文件
int fd = open("log.txt",O_WRONLY | O_CREAT | O_APPEND ,0666);
int cnt = 5;
char buffer[64];
while(cnt)
{
char buffer[64];
sprintf(buffer,"%s%d\n","hello log.txt",cnt--);
write(fd, buffer,strlen(buffer));
}
close(fd);
🏠 上层语言函数与底层接口函数的关系
- 从命名方式可以看出,C语言中的fopen,fclose,fwrite,fread等函数都是封装了操作系统提供的接口函数open,close,write,read。
- 但是,C语言是以FILE*文件指针来标识一个文件,而操作系统则是以fd文件描述符这个整型数字来标识一个文件。
- 当然,封装过程可不是简单的调用对应的函数。例如,fopen以"w"只写的方式打开文件,文件内容会被自动清空。但是,open传递参数flags=O_WRONLY,只以写的方式打开文件的话,里面的内容不会被清空,如果此时往里面写入数据,则会覆盖是写入。
本次分享到这里也就结束啦,如果各位看官有收获的话还希望给个三连支持一波,有什么意见或者建议也请评论区指出,谢谢大家!💛💛💛