[Linux系统编程]_文件编程(一)

这篇博客详细介绍了Linux系统编程中的文件操作,包括系统调用与库函数的区别、文件打开、写入、读取、光标移动、关闭等API的使用,以及文件操作的应用场景,如实现cp指令和修改配置文件。同时还探讨了文件描述符和文件操作原理,对比了open与fopen的差异,并展示了如何将整型数和结构体写入文件。
摘要由CSDN通过智能技术生成

嵌入式之路,贵在日常点滴

                                                                ---阿杰在线送代码

目录

一、系统调用

1.1 什么是系统调用

1.2 什么是库函数

1.3 将hello写入到文件1.txt流程

1.4 为什么要有缓冲区(补充) 

1.5 内核缓冲区和C标准缓冲区的区别 

二、文件编程常用API

1、文件打开 open() 

1.1 函数原型

1.2 参数描述

1.3代码举例

附:关于mode

创建文件 creat() 

2、文件写入  write()

2.1 函数原型

2.2 参数使用

2.3  代码举例

3、读取文件 read()

3.1 函数原型

3.2 参数使用

3.3 代码举例

4、文件光标移动 lseek()

4.1 函数原型

4.2 参数使用

4.3代码举例

4.4 三种使用举例 

5、文件关闭 close()

5.1 函数原型

5.2 参数使用

5.3 代码举例

三、文件操作小应用

实现cp指令

修改配置文件

四、研究往文件里面写入整型数和结构体(增加认知)

整型数 

结构体 

五、Linux文件操作原理简述

文件描述符:

文件操作原理: 

六、 open与fopen的区别

1. 来源

2. 移植性

3. 适用范围

4. 文件IO层次

5. 缓冲

七、用ANSIC标准中的C库函数进行文件编程 

fopen

fread

fwrite

fseek

用fopen、fread、fwrite、fseek来给一个文件写入结构体 

fputc

fgetc

feof 


一、系统调用

1.1 什么是系统调用

系统调用函数属于操作系统的一部分,是为了提供给用户进行操作的接口(API函数),使得用户态运行的进程与硬件设备(如CPU、磁盘、打印机、显示器)等进行交互。

  • 例如常见的系统调用 等等write read open …

1.2 什么是库函数

  1. 库函数可分为两类,一类是C语言标准库函数,一类是编译器特定的库函数。
  2. 库函数可以理解为是对系统调用函数的一层封装。尽管系统函数执行效率是比较高效而精简的,但有时我们需要对获取的信息进行更复杂的处理,或更人性化的需要,我们把这些处理过程封装成一个函数,再将许多这类的函数放在一个文件(库)一般放在 .lib文件。最后再供程序员使用。
  • #include<stdio.h>使用的时候包含头文件就可以使用其中的库函数了
  • 例如常见的库函数printf fwrite fread fopen…等等

1.3 将hello写入到文件1.txt流程

  1. 首先fopen打开文件 fwrite参数附上要写入的内容
  2. 文本内容来到C标准缓冲区
  3. 如果满足条件就刷新C标准缓冲区,调用系统函数write进行写(补充:满了就会自动刷新)
  4. write却只是把要写入的内容写到内核缓冲区
  5. 如果内核缓冲区满足条件就刷新内核缓冲区,系统调用sys_write将缓冲区内容写入到磁盘(补充:有个进程会定时刷新内核缓冲区)
  6. 此时有进程读取1.txt文件内容,发现内核缓冲区就有这个文件内容,就直接从内核缓冲区

1.4 为什么要有缓冲区(补充) 

定义:缓冲区就是内存里的一块区域,把数据先存内存里,然后一次性写入硬盘中的文件,类似于数据库的批量操作。
好处:减少对硬盘的直接操作,硬盘的执行速度为毫秒级别,内存为纳秒级别。在硬盘直接操作读写效率太低。 

1.5 内核缓冲区和C标准缓冲区的区别 

C语言标准库函数fopen()每打开一个文件时候,其都会对应一个单独一个缓冲区而内核缓冲区是公用的。 

二、文件编程常用API

1、文件打开 open() 

1.1 函数原型

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

1.2 参数描述

  • .pathname :文件路径+文件名(若不包含路径,则默认为当前路径)
  • .flats : (1) O_RDONLY 只读打开         O_WRONLY 只写打开         O_RDWR  可读可写打开

    (2)当我们附带了权限后,打开的文件就只能按照这种权限来操作。

    以上这三个常数中应当只指定一 个。下列常数是可选择的:     

        O_CREAT 若文件不存在则创建它。使用此选项时,需要同时说明第三个参数mode,用其说明该新文件的存取许可权限。

        O_EXCL 如果同时指定了OCREAT,而文件已经存在,则出错。       

        O_APPEND 每次写时都加到文件的尾端。

        O_TRUNC 属性去打开文件时,如果这个文件中本来是有内容的,而且为只读或只写成功打开,则将其长度截短为0。

当然也有组合使用(1.O_RDONLY |O_CREAT 只读如果不存在则创建)(O_WRONLY |O_CREAT 只写如果不存在则创建)(O_WRONLY | O_APPEND 文件存在则追加写入)

  • .mode:一定是在flags中使用了O_CREAT标志,mode记录待创建的文件的访问权限

  • . 返回值: 失败返回-1,成功返回 整形(fd:文件描述符)

        fd>0,文件打开成功且fd为文件标识符 fd<0,文件打开失败*/ 

1.3代码举例

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

int main()
{
        int fd;//file description

        fd = open("./file1",O_RDWR);

        printf("fd = %d\n",fd);

        return 0;
}

运行结果:

下面对flags(2)这类使用(|)进行附加使用的参数进行额外说明:

(1)O_CREAT:文件若不存在则创建

注意:需要额外说明文件操作权限参数mode 

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

int main()
{
        int fd;//file description

        //尝试打开当前路径下的文件file1.c
        fd = open("./file1",O_RDWR);

        //打开失败了
        if(fd == -1){
                printf("open file1 failed,fd = %d\n",fd);
                //尝试以可读可写的方式创建并打开文件
                fd = open("./file1",O_RDWR|O_CREAT,0600);
                if(fd > 0){
                        printf("create file1,fd = %d\n",fd);
                }
        }


        return 0;
}

运行结果:可以看到已经成功创建了file1.c

(2)O_EXCL:如果同时指定了OCREAT,而文件已经存在,则出错(返回值为-1)

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

int main()
{
        int fd;//file description

        fd = open("./file1",O_RDWR|O_CREAT|O_EXCL,0600);

        if(fd == -1){
                printf("file1 cunzai\n");
        }


        return 0;
}

运行结果:

  (3)O_APPEND:每次写时都加到文件的尾端(另起一行)

如果不使用这个参数,因为文件打开后光标是位于文件头的,写入数据会把原来的数据按长度覆盖。(本质上就是光标的问题)

原file1内容

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

int main()
{
        int fd;//file description
        char *buf = "a jie hen shuai";

        fd = open("./file1",O_RDWR|O_APPEND);

        printf("open suscess:fd = %d\n",fd);

        int n_write = write(fd,buf,strlen(buf));
        if(n_write != -1){
                printf("write %d byte to file\n",n_write);
        }

        close(fd);

        return 0;
}

运行后

若不加O_APPEND

  

(4)O_TRUNC清空原内容后写入

在每次打开文件写入之前,先把原有的内容清空后写入

原file1内容

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

int main()
{
        int fd;//file description
        char *buf = "a jie hen shuai";

        fd = open("./file1",O_RDWR|O_TRUNC);

        printf("open suscess:fd = %d\n",fd);

        int n_write = write(fd,buf,strlen(buf));
        if(n_write != -1){
                printf("write %d byte to file\n",n_write);
        }

        close(fd);

        return 0;
}

运行后:

  

附:关于mode

1、可读        r         4

2、可写        w        2

3、执行         x        1

创建文件 creat() 

创建文件的另一种方法(不可用于打开)

int creat(const char *pathname, mode_t mode);

/** mode **
S_IRUSR 可读            宏:4
S_IWUSR	可写            宏:2
S_IXUSR	可执行          宏:1
S_IRWXU	可读可写可执行   宏:7 */

简单使用示例:

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

int main()
{
                                 //可读可写
        int fd = creat("./file1.c",S_IRUSR|S_IWUSR);
        if(fd > 0){
                printf("文件创建成功\n");
        }else{
                printf("同名文件已经存在\n");
        }
        close(fd);
        return 0;
}
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值