基础文件操作

💘作者:泠沫
💘博客主页:泠沫的博客
💘专栏:初学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);

🏠 上层语言函数与底层接口函数的关系

  1. 从命名方式可以看出,C语言中的fopen,fclose,fwrite,fread等函数都是封装了操作系统提供的接口函数open,close,write,read。
  2. 但是,C语言是以FILE*文件指针来标识一个文件,而操作系统则是以fd文件描述符这个整型数字来标识一个文件。
  3. 当然,封装过程可不是简单的调用对应的函数。例如,fopen以"w"只写的方式打开文件,文件内容会被自动清空。但是,open传递参数flags=O_WRONLY,只以写的方式打开文件的话,里面的内容不会被清空,如果此时往里面写入数据,则会覆盖是写入。

本次分享到这里也就结束啦,如果各位看官有收获的话还希望给个三连支持一波,有什么意见或者建议也请评论区指出,谢谢大家!💛💛💛

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值