前言:
目录
首先,在正式进入本期主题之前,我先用C文件的接口带大家简单的回顾下,顺便带大家认识相关的接口函数等。
首先就是往文件里面进行写数据操作:
- #include
- #include
-
- #define LOG "log.txt"
-
- int main()
- {
- FILE *fp = fopen(LOG , "w");
-
- if(!fp)
- {
- perror("fopen");
- return 1;
- }
-
- const char *msg = "hello bit!\n";
- int count = 5;
- while(count--)
- {
- //fputs(msg,fp);
- fwrite(msg, strlen(msg), 1, fp);
- }
-
- fclose(fp);
- return 0;
- }
输出展示:

【解释说明】
fopen 函数以写入模式打开文件,返回一个文件指针 fp;perror 函数将输出错误信息到标准错误输出流。fwrite函数将字符串msg通过文件指针fp写入文件(除了这个外还有很多)首先就是读文件里面的数据操作:
- #define LOG "log.txt"
-
- int main()
- {
-
- FILE *fp = fopen(LOG, "r");
- if(!fp)
- {
- perror("fopen");
- return -1;
- }
- //正常进行文件操作
- while(1)
- {
- char line[128];
- if(fgets(line, sizeof(line), fp) == NULL) break;
- else printf("%s", line);
- }
-
- fclose(fp);
- return 0;
- }
输出展示:

【解释说明】
如上,是我们之前学的文件相关操作。还有 fseek ftell rewind 的函数。
操作文件,除了上述C接口(当然,C++也有接口,其他语言也有),我们还可以采用系统接口来进行文件访问.
先来直接以代码的形式,实现和上面一模一样的代码(写操作):
- #include
- #include
- #include
- #include
- #include
- #include
-
- int main()
- {
- umask(0);
- int fd = open("myfile", O_WRONLY|O_CREAT, 0644);
- if(fd < 0){
- perror("open");
- return 1;
- }
- int count = 5;
- const char *msg = "hello bit!\n";
- int len = strlen(msg);
- while(count--){
- write(fd, msg, len);
- //fd: 后面讲, msg:缓冲区首地址, len: 本次读取,期望写入多少个字节的数据。
- //返回值:实际写了多少字节数据
- }
- close(fd);
- return 0;
- }
- #include
- #include
- #include
- #include
- #include
- #include
-
- int main()
- {
- int fd = open("myfile", O_RDONLY);
- if(fd < 0){
- perror("open");
- return 1;
- }
- const char *msg = "hello bit!\n";
- char buf[1024];
- while(1){
- ssize_t s = read(fd, buf, strlen(msg));//类比write
- if(s > 0){
- printf("%s", buf);
- }
- else{
- break;
- }
- }
- close(fd);
- return 0;
- }
接下来,我首先带大家认识相关的接口。随后大家在来理解上述这两段代码!!

【解释说明】
参数:
path:要打开的文件的路径字符串。flags:打开文件的标志,可以使用一或多个以下标志的位或运算符 |第一个参数很好理解,对于第二个参数大家可能存在些疑惑我在这里重点讲讲关于这个标志的问题。
💨 首先,引入一个问题:OS是如何让用户给自己传递标志位的呢?

接下来,我给大家写个简单的 demo 样例帮助大家理解上述逻辑:
- #include
-
- #define ONE 0x1
- #define TWO 0x2
- #define THREE 0x4
- #define FOUR 0x8
- #define FIVE 0x10
-
- // 0000 0000 0000 0000 0000 0000 0000 0000
- void Print(int flags)
- {
- if(flags & ONE) printf("hello 1\n"); //充当不同的行为
- if(flags & TWO) printf("hello 2\n");
- if(flags & THREE) printf("hello 3\n");
- if(flags & FOUR) printf("hello 4\n");
- if(flags & FIVE) printf("hello 5\n");
- }
-
-
- int main()
- {
- printf("--------------------------\n");
- Print(ONE);
- printf("--------------------------\n");
- Print(TWO);
- printf("--------------------------\n");
- Print(FOUR);
- printf("--------------------------\n");
-
- Print(ONE|TWO);
- printf("--------------------------\n");
-
- Print(ONE|TWO|THREE);
- printf("--------------------------\n");
-
- Print(ONE|TWO|THREE|FOUR|FIVE);
- printf("--------------------------\n");
-
- return 0;
- }
输出展示:

【解释说明】
ONE的二进制表示是:0000 0000 0000 0000 0000 0000 0000 0001,TWO的二进制表示是:0000 0000 0000 0000 0000 0000 0000 0010,依此类推。Print函数,它接受一个整数参数flags,这个参数表示一组标志位的组合。在函数内部,使用位运算和按位与操作符&来检查每个标志位是否被设置。有了上述认识,大家在返回去看 open() 函数中的 flags参数,我想就很明显了。当我们在man手册中往下面翻的时候就会看到如下内容:

接下来,我们通过写代码的方式来进行理解!!
首先,有如下代码示例:
- int main()
- {
- int fd = open(LOG,O_WRONLY);
- if(fd == -1)
- {
- printf("fd: %d, errno: %d, errstring: %s\n", fd, errno, strerror(errno));
- }
- else printf("fd: %d, errno: %d, errstring: %s\n", fd, errno, strerror(errno));
-
- close(fd);
- return 0;
- }
-
输出展示:

【解释说明】
fd)、错误代码(errno)和错误字符串(strerror(errno));LOG这个文件,因此最后的输出肯定是发生报错。解决方法就是在我们 open 的时候,再加上 【o_CREAT】这个标志:

输出展示:

然而,此时出现了一个奇怪的现象,我们通过查看得知 log.txt 文件的权限是处于乱码的情况:

因此,基于上述情况的出现。我们一般在用的时候一般不用 带两个参数的 open() ,而是用带三个参数的open() 函数

【解释说明】
mode_t类型的参数,用于设置文件的权限;O_CREAT标志创建文件时才会生效;0644表示文件所有者具有读写权限,其他用户只有读权限。基于上述情况,我们在后面加上相应的权限(我这里加的是0666):

输出展示:

【解释说明】

那么要如何保障这里的权限不受系统的影响呢?—— 我们可以自己设置

接下来,我们对代码进行修改操作:

输出展示:

【注意】
接下来,我们就需要往文件中写入数据了。在C++中,系统提供 write() 函数来进行写操作。

代码展示:

输出展示:

上述完成写入数据,接下来就是从文件中读出数据。在C++中,系统提供了 read() 函数
man手册查询:

代码展示:

输出展示:

【小结】
上面的 fopen fclose fread fwrite 都是C标准库当中的函数,我们称之为库函数(libc);
open close read write lseek 都属于系统提供的接口,称之为系统调用接口
回忆一下我们讲操作系统概念时,画的一张图:
