Linux系统编程之文件篇

本文介绍了Linux下进行文件操作的基本步骤,包括使用open函数打开文件,通过read和write函数进行读写操作,使用close函数关闭文件,以及如何设置文件权限和使用lseek管理文件光标。示例代码演示了如何创建、读取和写入文件,以及实现简单的cp命令功能。
摘要由CSDN通过智能技术生成

一、Linux文件编程的一般步骤

  1. 在Linux底下要操作一个文件,需要先open一个文件,获得一个文件描述符,然后对文件进行读写操作,最后在关闭文件即可;

  1. 对文件进行操作时,一定要先打开文件,文件成功打开之后才能操作,如果打开失败,那就不用进行后面的操作了,最后读写完成之后一定要关闭文件;

  1. 文件平时是存放在块设备中的系统文件中的,称之为静态文件;当我们去打开一个文件,Linux的内核进程会先建立一个打开文件的数据结构,然后内核在内存管理中申请一段内存,再将静态内存的内容从块设备读取到内核指定地址管理存放;

  1. 打开文件后,对于这个文件的读写操作,都是针对于内存中的一份动态文件,当我们进行读写操作时,静态文件和动态文件其实是不同步的,只有在动态文件关闭之后,动态文件的内容才会更新到静态文件中。

二、读取/创建文件

  1. open函数原型

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

    int open(const char *pathname, int flags);
    int open(const cahr *pathname, int flags, mode_t mode );
    int creat(const char *pathname, mode_t mode);
  1. 参数说明

  • pathname:要打开文件的名字(含路径,缺省为当前路径);

  • flags(权限):O_RDONLY(只读打开);

O_WRONLY(只写打开);

O_RDWR(可读可写打开);

  • 以上flags的三个参数只能选用一个,下列的参数是可选择的;

  • O_CREAT:若文件不存在则创建文件,使用该项需要配置mode,说明文件的存取许可权限;

  • O_EXCL:如果文件已存在,则返回错误;

  • O_APPEND:每次写时都写到文件的尾端;

  • O_TRUNC:会将文件原本的内容全部丢弃,文件大小变为0;

  • mode:创建模式,在flags中使用了O_CREAT标志;

  • 常见创建模式:

宏表示        数字
S_IRUSR        4    可读
S_IWUSR        2    可写
S_IXUSR        1    可执行
S_IRWXU        7    可读、可写、可执行
  1. 返回值:

  • open:打开成功返回一个文件描述符,失败返回-1;

  • creat:创建成功返回一个文件描述符,失败返回-1。

  1. demo编写

//这个demo在当前文件夹打开文件,如果文件不存在,则创建文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>

int main()
{
    int fd;        //file description,文件描述符,定义一个文件描述符
    fd = open("./file_1",O_RDWR);
    if(fd == -1){
        printf("open file_1 failed!\n");
        fd = open ("./file_1",O_RDWR|O_CREAT,0600);    //0600是文件的权限 
        if(fd > 0){
            printf("creat file_1 success!!\n");
        }
    }
    printf("fd = %d\n",fd);
    return 0;
}

三、读写文件

  1. write函数原型

SYNOPSIS
    #include <unistd.h>

    ssize_t write(int fd, const void *buf, size_t count);
    ssize_t read(int fd, void *buf, size_t count);
  1. 参数说明

  • fd:文件描述符;

  • *buf:指定内存的指针,也可以是一个数组

  • count:读写的字节数。

  1. 返回值

  • write

  • 当有错误时,返回-1,错误代码可以用errno捕捉;

  • 成功写入,会返回实际写入的字节数(len)。

  • read

  • 返回值为实际读取到的字节数,如果返回0,则表示读取到了文件尾部或者无可读取的数据;

  • 对于网络套接字接口,返回值可能小于count,但是这并不是错误。

  1. demo编写

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

int main()
{
    int fd;        //file description,文件描述符
    char *buf = "DaQiangYYDS";
    fd = open("./file_1",O_RDWR);        //打开file文件
    //打开失败,则创建文件
    if(fd == -1){
        printf("open file_1 failed!\n");
        fd = open ("./file_1",O_RDWR|O_CREAT,0600);    //0600是文件的权限 
        if(fd > 0){
            printf("creat file_1 success!!\n");
        }
    }
    printf("open success : fd = %d\n",fd);    

    int n_write = write(fd,buf,strlen(buf));
    //往文件进行写入,后关闭
    if(n_write != -1){
        printf("write %d byte to file_1\n",n_write);
    }
    //重新定位光标    
        lseek(fd,0,SEEK_SET);
    //读取文件内容
    char *readBuf;
    readBuf = (char *)malloc(sizeof(char)*n_write + 1);
    int n_read = read(fd,readBuf,n_write);
    printf("read byte : %d\ncontext : %s\n",n_read,readBuf);
    //关闭文件
    close(fd);
    return 0;
}

四、文件光标

  1. lseek函数原型

SYNOPSIS
    #include <sys/types.h>
    #include <unistd.h>

    off_t lseek(int fd, off_t offset, int where);
  1. 参数

  • fd:文件描述符

  • offset:偏移量,以字节为单位

  • where:用于定义offest偏移量对应的参考值,且选择以下其中一个参数;

//    宏定义
//    SEEK_SET        文件头
//    SEEK_CUR        当前位置
//    SEEK_END        文件尾
  1. 返回值

  • 成功返回文件头部到参数where的位置的偏移量(字节为单位);

  • 错误返回-1,并设置errno值

  1. 应用

  • 调整当前光标的位置,保证读写操作的正常运行;

  • 计算文件的大小,将where设置为SEEK_END,则lseek的返回值就是文件的大小。

  1. demo编写

  • 参考第三部分的demo;

五、关闭文件

  1. close函数原型

SYNOPSIS
    #include <unistd.h>

    int close(int fd);
  1. 参数

  • fd:文件描述符

  1. 返回值

  • 成功:返回0;

  • 错误:返回-1,并设置errno值。

六、cp指令的实现demo

  1. 实现思路

  • C语言的参数:./a.out [file1] [file2]

  • 代码思路:

  • 打开src(源文件)

  • 读取src(源文件)到buf(缓冲区)

  • 打开/创建des(目标文件)

  • 将buf(缓冲区)写道des(目标文件)

  • close(关闭)两个文件

  1. demo编写

//头文件区
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>

//主函数区
int main(int argc,char **argv)
{
    int fd_Src;            //源文件标识符
    int fd_Des;            //目标文件标识符
    char *readBuf = NULL;        //读取文件的区域指针
    printf("pararm number : %d\n",argc);
    //如果参数输入错误,则退出程序
    if(argc != 3){
        printf("pararm error!\n");
        exit(-1);
    }
    //读取源文件
    fd_Src = open(argv[1],O_RDWR);
    int size = lseek(fd_Src,SEEK_SET,SEEK_END);    //利用光标定位的返回值计算文件的大小
    lseek(fd_Src,SEEK_SET,SEEK_SET);        //重置光标
    readBuf =(char *)malloc(sizeof(char)*size + 8);    //开辟相应的空间大小,并大一些
    int n_read = read(fd_Src,readBuf,size);        //读取size的内容
    //读取正常,返回值为非负整数
    if(n_read != -1){
        printf("read success\n");
        printf("read Byte : %d\n",n_read);
    } 
    //读取异常,返回值为-1
    else{
        printf("read failed\n");
    }
    close(fd_Src);
    //写入目标文件
    fd_Des = open(argv[2],O_RDWR|O_CREAT|O_TRUNC,0600);
    int n_write = write(fd_Des,readBuf,strlen(readBuf));
    //写入正常,返回值为非负整数
    if(n_write != -1){
        printf("write success\n");
        printf("write Byte : %d\n",n_write);
    }
    //写入异常,返回值为-1
    else{
        printf("write failed\n");
    }
    close(fd_Des);
    
    return 0;
}
  1. 运行效果

  • 传入两个参数,源文件,目标文件

  • 对比两个文件的不同用vimdiff指令;

  • 退出输入“:qall“即可

七、修改配置文件demo

  1. 在前文件夹内有一个TEST.config的配置文件,内容如下

  1. 将文件中的LENG=9改成LENG=5

  1. demo编写

//头文件区
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>

//主函数区
int main(int argc,char **argv)
{
    int fd_Src;            //源文件标识符
    char *readBuf = NULL;        //读取文件的区域指针
    //如果参数输入错误,则退出程序
    if(argc != 2){
        printf("pararm error!\n");
        exit(-1);
    }
    //读取源文件
    fd_Src = open(argv[1],O_RDWR);
    int size = lseek(fd_Src,SEEK_SET,SEEK_END);    //利用光标定位的返回值计算文件的大小
    lseek(fd_Src,SEEK_SET,SEEK_SET);        //重置光标
    readBuf =(char *)malloc(sizeof(char)*size + 8);    //开辟相应的空间大小,并大一些
    int n_read = read(fd_Src,readBuf,size);        //读取size的内容
    //读取正常,返回值为非负整数
    if(n_read != -1){
        printf("read success\n");
        printf("read Byte : %d\n",n_read);
    } 
    //读取异常,返回值为-1
    else{
        printf("read failed\n");
    }
    char *p = strstr(readBuf,"LENG=");    //查找“LENG=”字符串,并返回第一个字符的地址
    if(p==NULL){
        printf("not found\n");
        exit(-1);
    }
    p = p+strlen("LENG=");
    *p = '5';
    lseek(fd_Src,SEEK_SET,SEEK_SET);
    int n_write = write(fd_Src,readBuf,strlen(readBuf));
    close(fd_Src);
    
    return 0;
}



  1. 运行效果

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

二灰酱

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值