Linux中的基础IO -- C语言文件操作,系统级文件操作(open, write, read),文件描述符,重定向,dup2,缓冲区机制

目录

1. 理解文件

2. C语言中文件操作的接口

2.1 打开文件 -- fopen

2.2 写文件 -- fwrite

2.3 读文件 -- fread

2.4 输出信息到显示器的几种方法

2.5 stdin,stdout,stderr

3. 系统文件IO

3.1 一种传递标志位的方法 -- 位图

3.2 接口介绍

3.2.1 打开文件 -- open

3.2.2 写文件 -- write

3.2.3 读文件 -- read

3.3 文件描述符fd

3.3.1 理解文件描述符

3.3.2 文件描述符的分配规则

 3.3.3 重定向

3.3.4 使用dup2系统调用进行重定向

3.3.5 重定向的操作

 4. 理解“Linux系统下一切皆文件”

5. 缓冲区

5.1 什么是缓冲区

5.2 为什么要引入缓冲区机制

5.3 缓冲类型

5.4 简单实现C标准库的文件操作接口


1. 理解文件

        (1)文件是在磁盘中的,磁盘是永久性存储介质,所以文件在磁盘上的存储是永久性的。磁盘是外设,即输入输出设备,所以对磁盘上的文件的所有操作,本质上都是对外设的输入和输出,简称IO。

        (2)Linux系统下一切皆文件,如键盘,显示器,网卡,磁盘等,系统都会对其进行管理起来。

        (3)文件 = 文件属性(元数据)+ 文件内容。对于0KB的空文件也是要占用磁盘空间,所有的文件操作本质上就是对文件内容和文件属性进行操作

        (4)对文件的操作都是正在运行的程序进行操作的,所以对文件的操作就是进程对文件的操作。但是文件在磁盘中,磁盘的管理者是操作系统,所以对磁盘中的文件进行操作绕不开操作系统。文件的读写本质不是通过C/C++的库函数来操作的,而是通过文件相关的系统调用接口实现的,C/C++的库函数只是封装了这些系统调用接口,使用户用起来更加的方便。

2. C语言中文件操作的接口

2.1 打开文件 -- fopen

#include <stdio.h>

int main()
{
    FILE *fp = fopen("myfile", "w");    //以‘w’的方式打开myfile文件
    if(!fp) {
    printf("fopen error!\n");
    }
    while(1);
    fclose(fp);
    return 0;
}

        打开的myfile文件默认是在当前程序的工作目录下的,myfile文件的绝对路径就是当前程序的工作目录 + 文件名。 

        使用 ls /proc/进程id -l ,命令查看当前正在运⾏进程的信息:

        cwd:指向当前进程运行目录的一个符号链接。

        exe:指向启动当前进程的可执行文件(完整路径)的符号链接。

        打开文件是进程打开的,进程知道自己在哪个工作目录下,所以文件不带路径,进程默认会打开工作目录下的文件。以 ‘w’ 的方式打开即使没有对应的文件,也会在该进程的工作目录下创建一个。

2.2 写文件 -- fwrite

#include <stdio.h>
#include <string.h>

int main()
    {
    FILE *fp = fopen("result", "w");
    if(!fp){
        printf("fopen error!\n");
    }
    const char *msg = "hello xiaoc!\n";
    int count = 5;
    while(count--){
        fwrite(msg, strlen(msg), 1, fp);
    }
    fclose(fp);
    return 0;
}

        上述fwrite接口的意思是向 fp 中写入 1个 大小为 strlen(msg) 的 msg 。 循环写五次,得到如下结果:

2.3 读文件 -- fread

#include <stdio.h>
#include <string.h>

int main()
{
    FILE *fp = fopen("result", "r");
    if(!fp)
    {
        printf("fopen error!\n");
        return 1;
    }

    while(1)
    {
        //注意返回值和参数,仔细查看man⼿册关于该函数的说明
        char buf[1024];
        memset(buf, 0 ,sizeof(buf));
        size_t s = fread(buf, sizeof(buf)-1, 1, fp);
        printf("%s", buf);

        if(feof(fp))
        {
                break;
        }
    }
    fclose(fp);
    return 0;
}

2.4 输出信息到显示器的几种方法

#include <stdio.h>
#include <string.h>

int main()
{
        printf("hello printf\n");
        fprintf(stdout, "hello fprintf\n");
        const char *msg = "hello fwrite\n";
        fwrite(msg, strlen(msg), 1, stdout);
        return 0;
}

        这里列举了三种方法,分别是printf,fprintf,fwrite。

2.5 stdin,stdout,stderr

        C程序会默认打开三个输入输出流,分别是 stdin,stdout,stderr。这三个流的类型都是FILE*。

        stdin:标准输入 -- 键盘文件。

        stdout:标准输出 -- 显示器文件。

        stderr:标准错误 -- 显示器文件。

知识点1:
        为什么要默认打开这三个输入输出流?
                因为程序是用来做数据处理的,需要有一个数据输入源和数据输出地,所以在默认情况下会打开这三个输入输出流作为输入源和输出地。

3. 系统文件IO

        使用fopen,ifstream这种打开文件的方式是语言层的方案,其实这些语言层的函数都封装了系统层面的文件操作函数,底层都是调用系统的接口进行操作的。

3.1 一种传递标志位的方法 -- 位图

#include <stdio.h>

#define ONE   1 // 0000 0001
#define TWO   2 // 0000 0010
#define THREE 4 // 0000 0100

void func(int flags)
{
        if (flags & ONE) printf(" flags has ONE! ");
        if (flags & TWO) printf(" flags has TWO! ");
        if (flags & THREE) printf(" flags has THREE! ");
        printf("\n");
}

int  main()
{
        func(ONE);
        func(THREE);

        func(ONE | TWO);
        return 0;
}

        位图的定义就是使用一个变量中的比特位来当作标志位。如上述代码,定义的ONE,TWO,THREE对应的就是变量中比特位的第0位,第1位,第2位为 1。然后在func函数中使用与运算就可以判断传递的flags中是否存在上述标志位。如果想传递多个标志位,就可以在传递参数的时候将多个标志位进行或操作。

3.2 接口介绍

3.2.1 打开文件 -- open

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);

        pathname:要打开或创建的目标文件路径。

        flags:打开文件时,可以传⼊多个参数选项,这里就是使用位图的方式来传递标志位,⽤下⾯的⼀个或者多个常量进⾏“或”运算,构成flags。

        O_RDONLY:只读打开。
        O_WRONLY:只写打开。
        O_RDWR:读,写打开。
        这三个常量,必须指定⼀个且只能指定⼀个。

        O_CREAT:若⽂件不存在,则创建它。需要使⽤mode选项,来指明新⽂件的访问权限。
        O_APPEND:追加写。

        mode:指定创建文件时的默认权限。
        返回值:
                成功:返回新打开的⽂件描述符。
                失败:返回 -1。

3.2.2 写文件 -- write

        下面代码中open函数传入的参数表示:以只读(O_WRONLY),清除(O_TRUNC)的方式打开文件,若文件不存在则创建该文件(O_CREAT),并把默认权限设置为666。

        只写入一次,write函数表示向 fd 文件描述符指定的文件中写入大小为 strlen(msg)的msg。

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main()
{
        //设置文件权限的掩码,如果没有设置使用系统中的文件权限掩码
        umask(0);       
        //对应C语言的w方式打开
        int fd = open("log.txt", O_CREAT | O_WRONLY | O_TRUNC, 0666);   

    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值