文件操作系统

文件
在之前学习C语言文件操作时,我们了解过什么是文件,这里简单回顾一下:

文件存在磁盘中,文件有分为程序文件、数据文件;二进制文件和文本文件等。

详细描述见文章:文件操作——C语言

文件在磁盘里,磁盘是永久性存储介质,因为文件在磁盘上的存储是永久性的;
磁盘是外设(是输入设备也是输出设备);
本质上对磁盘是文件的所有操作,都是对外设的输入和输出;也就是I/O。
对于文件的认识:

文件 = 文件内容 + 文件属性
文件大小是0KB的文件也是占用磁盘空间的
所有对于文件的相关操作都是对文件内容和文件属性就行操作。
在系统层面理解

我们操作文件(打开,关闭文件),本质上是进程对于文件的操作;
磁盘的管理者是操作系统;
我们在C/C++使用库函数来对文件进行读写操作,本质上是通过文件相关的系统调用去完成的。
C文件操作
打开和关闭文件
在C语言当中,我们通过fopen来打开文件,fclose来关闭文件;

fopen:打开文件,如果打开成功返回一个FILE*类型的指针,执行被打开的文件;打开失败则返回NULL;
fclose:关闭文件,传参FILE*类型的指针,关闭指定文件。
#include <stdio.h>
int main()      
{      
    FILE* fp = fopen("log.txt","w");//以读方式打开,文件不存在就新建      
    if(fp == NULL){      
        perror("fopen");      
        return 1;      
    }      
    //....      
    fclose(fp);//关闭文件                                                              
    return 0;                                             
}  
1
2
3
4
5
6
7
8
9
10
11
12
打开文件的方式


我们知道在C语言的fopen接口打开文件是有很多打开方式

r:以读方式打开、w以写方式打开、a以追加方式打开。

r方式,当文件不存在时就打开文件失败;
w方式,当文件不存在时就新建文件(在当前工作路径下创建,进程当中存放了当前工作路径);如果文件存在会清空当前文件的内容;然后在进入写入。
a方式,追加,当文件不存在就新建文件;如果文件已经存在,打开时不会清空文件内容,而是在文件末尾进行写入
写文件
当我们以w/r方式打开一个文件,我们要将内容写到文件当中;

 

我们可以使用fputc、fputs、fwrite、fprintf进行文件的写入;

#include <stdio.h>
int main()      
{      
    FILE* fp = fopen("log.txt","w");//以读方式打开,文件不存在就新建      
    if(fp == NULL){      
        perror("fopen");      
        return 1;      
    }      
    for(char ch = 'a';ch <= 'z';ch++){    
        fputc(ch,fp);    
    }    
    char* str = (char*)"I love you\n";    
    fputs(str,fp);    
    int x = 100;    
    fprintf(fp,"x = %d\n",x); 
    fclose(fp);//关闭文件                                                              
    return 0;                                             
}  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18


文件读取
我们以r方式打开一个文件,我们要像读取这个文件的内容,我们可以使用fgetc、fgets、fscanf进入文件内容的读取操作:

#include <stdio.h>
int main()      
{      
    FILE* fp = fopen("log.txt","w");//以读方式打开,文件不存在就新建      
    if(fp == NULL){      
        perror("fopen");      
        return 1;      
    }
    for(int i = 0;i<26;i++){    
        printf("%c",fgetc(fp));    
    }    
    printf("\n");    
    char buff[20];    
    fgets(buff,12,fp);    
    //buff[11] = '\0';    
    printf("%s",buff);    
    int x;    
    fscanf(fp,"x = %d",&x);    
    printf("x = %d\n", x);  
    fclose(fp);//关闭文件                                                              
    return 0;                                 
}  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22


stdin/stdout/stderr
在我们程序运行时,C语言它会默认打开三个文件:stdin、stdout和stderr;

我们可以发现这三个都是文件类型指针

 

系统文件I/O
在上述C语言的文件操作fopen、fclose都是语言层提供给我们的文件操作接口;以及C语言的stdin、stdout、stderr;C++中的cin、cout、cerr都是语言层提供给我们的方案;

我们知道文件的管理者是操作系统,所以我们对文件操作都要经过操作系统;

那也就是说语言层的文件操作接口,其底层都封装了系统调用。

1. 传递多个标志位的方法
在之前的习惯中,我们通常使用一个参数来作为一个标记位;这样我们在传递多个标志位时就需要传递多个参数。

现在来了解一种使用一个参数来传递多个标志位的方法:

使用一个bit为来作为一个标识符,这样使用一个参数就可以表示多个标志位了。
#include <stdio.h>
#define ONE 0001   //0000 0001
#define TWO 0002   //0000 0010
#define THREE 0004 //0000 0100   
void func(int flag){    
    if(flag & ONE)  printf("ONE ");    
    if(flag & TWO)  printf("TWO ");    
    if(flag & THREE)  printf("THREE ");    
    printf("\n");    
}    
int main()    
{    
    func(ONE);    
    func(ONE | TWO);    
    func(ONE | THREE);    
    func(ONE | TWO | THREE);  
    return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18


这样就可以使用一个参数,传递多个标志位了。
Linux操作系统open接口就使用了一个参数来传递多个标志位。
2. 打开文件open
在语言层面,我们使用的fopen,它本质上就是对系统调用的封装;

 

可以看到open是一个系统调用;它的作用就是打开一个文件,也可能会创建一个新的文件。
我们可以看到open函数它存在一个两个参数的,也存在一个三个参数的;

pathname:表示要打开文件的文件名(不带路径就默认在当前工作路径下)
flags:表示文件的打开方式,存在多个标志位
mode:表示新建文件时,文件的默认权限
文件名pathname
这个想必就不用多说了,表示要打开文件的文件名;

不带路径时,就表示在当前工作路径下打开文件。(进程中存在当前工作路径cwd)

标志位flags
通过查看open函数说明可以看到,flags存在非常多的标志位;这里列举一些常用的选项

O_RDONLY只读、O_WRONLY只写、O_RDWR读写;
O_CREAT:文件不存在时就新建文件
O_TRUNC:打开文件时,文件存在就清空文件内容
O_APPEND:打开文件时,以追加形式打开。
这里flags表示的就是文件的打开方式;

首先就是:只读、只写和读写;在我们打开文件时必须指定一个且只能指定一个。

O_CREAT

在我们打开一个文件时,如果这个文件不存在,那open函数就会直接返回-1表示文件打开失败;

而我们带了O_CREAT选项,就表明当文件不存在时,就新建文件;(这里新建文件要指明新建文件的权限,否则创建出来文件的权限就是乱码)

#include <stdio.h>      
#include <sys/types.h>      
#include <sys/stat.h>      
#include <fcntl.h>
int main()      
{      
    int fd = open("love.txt",O_CREAT | O_WRONLY,0666);      
    if(fd < 0){      
        perror("open");      
        return 1;                                                                                                 
    }                                                                                                            
    return 0;                                                                                                    
}    
1
2
3
4
5
6
7
8
9
10
11
12
13


一般情况下,在以写方式打开文件,文件不存在就新建,就要指明文件的权限。
(以只读读方式O_RDONLY,文件不存在新建出的文件是空的,没有什么意义)
O_TRUNC

当我们打开一个文件时,如果这个文件已经存在了,那就打开这个已有的文件;

如果我们带了O_TRUNC选项,就表示清空这个文件的内容;

#include <stdio.h>      
#include <sys/types.h>      
#include <sys/stat.h>      
#include <fcntl.h>
int main()      
{      
    int fd = open("love.txt",O_CREAT | O_WRONLY | O_TRUNC,0666);      
    if(fd < 0){      
        perror("open");      
        return 1;                                                                                                 
    }                                                                                                            
    return 0;                                                                                                    
}
1
2
3
4
5
6
7
8
9
10
11
12
13


O_APPEND

在C语言的文件操作中,fopen打开文件,w就是以写方式打开、文件不存在就新建、文件存在就清空文件的内容;(这就对应了上述选项的O_WRONLY、O_CREAT、O_TRUNC)

但是我们fopen还可以以a方式打开文件,也就是追加方式;这里的O_APPEND就是以追加的方式打开文件。

这里我们先看一种现象:

#include <stdio.h>      
#include <sys/types.h>      
#include <sys/stat.h>      
#include <fcntl.h>
int main()      
{      
    int fd = open("love.txt",O_CREAT | O_WRONLY,0666);      
    if(fd < 0){      
        perror("open");      
        return 1;                                                                                                 
    }
    char buff[] = "abcdef";
    write(fd,buff,strlen(buff));  
    return 0;                                                                                                    
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15


可以看到,我们不带O_APPEND选项,写入的时候是在文件的开头位置进行写入的。
#include <stdio.h>      
#include <sys/types.h>      
#include <sys/stat.h>      
#include <fcntl.h>
int main()      
{      
    int fd = open("love.txt",O_CREAT | O_WRONLY | O_APPEND,0666);      
    if(fd < 0){      
        perror("open");      
        return 1;                                                                                                 
    }
    char buff[] = "abcdef";
    write(fd,buff,strlen(buff));  
    return 0;                                                                                                    
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15


文件权限mode
当打开文件,文件不存在,我们还带了O_CREAT选项时;如果我们不带文件的权限,那新建文件的权限就是乱码;

而新建的文件的权限:文件权限 = 默认权限 &(~umask)

3. 关闭文件
关闭文件的系统调用close,根据文件描述符,关闭指定文件。

 

对于这里的fd,它指的是文件描述符,当我们打开文件成功时,会返回给我们该文件的文件描述符;
我们对指定文件的读写操作,以及关闭文件都要使用指定文件的文件描述符。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值