【Linux系统编程(文件编程)】之复现cp指令、修改文件应用

一、文件操作原理

文件描述符:

  1. 对于内核而言,所有打开文件都由文件描述符引用。文件描述符是一个非负整数。当进程打开一个文件或创建一个新文件时,内核向进程返回一个文件描述符。当读写一个文件时,用open或creat返回的文件描述符标识该文件,将其作为参数传递给read或write。
    按照惯例,UNIX shell使用文件描述符 0 与进程的标准输入相结合,文件描述符 1 与进程的标准输出相结合,文件描述符 2 与进程的标准错误输出相结合。STDIN_FILENO、STDOUT_FILENO、STDERR_FILENO 这几个宏代替了 0 1 2 这几个魔数。
  2. 文件描述符,这个数字在一个进程中表示一个特定的含义,当我们open一个文件时,操作系统在内存中构建了一些数据结构来表示这个动态文件,然后返回应用程序一个数字作为文件描述符,这个数字就和我们内存中维护的这个动态文件的这些数据结构绑定上了,以后我们应用程序如果向操作这个动态文件,只需要用这个文件描述符区分。
  3. 文件描述符的作用域是当前进程,出了这个进程文件描述符就没有意义了。

open函数打开文件,打开成功返回一个文件描述符,打开失败,返回-1。

标准输入、标准输出的例子:
在这里插入图片描述

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

int main()
{
        char readBuf[128]={0};
        int n_read = read(0, readBuf, 5);
        int n_write = write(1, readBuf, strlen(readBuf));
        printf("\ndone!\n");
        return 0;
}

二、文件操作步骤

打开/创建文件
读取/写入文件
关闭文件
  1. Linux中要操作一个文件,一般是先 open 一个文件,得到文件描述符,然后对文件进行读写操作(或其它操作),最后是 close 关闭文件。
  2. 强调一点:我们对文件进行操作时,一定要先打开文件,打开成功之后才能进行操作,如果打开失败,就不用进行后边的操作了,最后读写完成后,一定要关闭文件,否则会造成文件损坏。
  3. 文件平时是存放在块设备中的文件系统中的,这种文件叫做静态文件,当我们open一个文件时,Linux内核作大操作包括:内核在进程中建立一个打开文件的数据结构,记录下我们打开的这个文件;内核在内存中申请一段内存,并且将静态文件的内容从块设备中读取到内核中特定地址管理存放(叫动态文件)。
  4. 打开文件以后,以后都是对这个文件的读写操作,都是针对内存中这份动态文件的,而非静态文件。当对动态文件读写后,内存中的动态文件与块设备中的静态文件就不同步了,当close被进程调用关闭动态文件时,close内部内核将内存中的动态文件的内容去更新(同步)到块设备中的静态文件。
  5. why 这么设计,不直接对块设备直接操作?
    块设备本身读写非常不灵活,是按块读写的,而内存是按字节单位操作的,而且可以随机操作,很灵活。

在这里插入图片描述

三、实现 cp 复制指令

在这里插入图片描述

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

int main(int argc, char **argv)
{
        if(argc != 3){
                printf("param error\n");
                exit(-1);
        }

        printf("argc=%d\n", argc);
        printf("argv[0]=%s\n",argv[0]);
        printf("argv[1]=%s\n",argv[1]);
        printf("argv[2]=%s\n",argv[2]);


        int fd_src, fd_des;
        char *readBuf=NULL;
        // 打开src
        fd_src = open(argv[1], O_RDWR);
        int size = lseek(fd_src, 0, SEEK_END);
        lseek(fd_src, 0, SEEK_SET);
        readBuf = (char *)malloc(size + 8);
        // 读取
        int n_read = read(fd_src, readBuf, size);


        // 创建或打开des
        fd_des = open(argv[2], O_RDWR|O_CREAT|O_TRUNC, 0600); //无则创建 有则清空
        // 写入
        int n_write = write(fd_des, readBuf, strlen(readBuf));

        // 关闭
        close(fd_src);
        close(fd_des);

        return 0;
}

四、修改配置文件

修改配置文件

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

int main(int argc, char **argv)
{
        if(argc != 2){
                printf("param error\n");
                exit(-1);
        }


        int fd;
        char *readBuf=NULL;
        // 打开
        fd = open(argv[1], O_RDWR);

        /*
        int num = lseek(fd, 0, SEEK_CUR);
        printf("how many %d\n", num);//0
        */

        int size = lseek(fd, 0, SEEK_END);
        lseek(fd, 0, SEEK_SET);

        // 读取
        readBuf = (char *)malloc(size + 8);
        int n_read = read(fd, readBuf, size);

        // modify
        char *p = strstr(readBuf, "LENG=");//修改5为其他
        p = p + strlen("LENG=");
        *p = '9';

        // 写入
        lseek(fd, 0, SEEK_SET);
        int n_write = write(fd, readBuf, strlen(readBuf));
        // 关闭
        close(fd);

        return 0;
}

五、写一个整数到文件

在这里插入图片描述

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

int main()
{
        int fd;
        int data = 100;
        int data2;
        fd = open("./file", O_RDWR);

        //ssize_t write(int fd, const void *buf, size_t count);
        int n_write = write(fd, &data, sizeof(int));

        lseek(fd, 0, SEEK_SET); //重要

        //ssize_t read(int fd, void *buf, size_t count);
        int n_read = read(fd, &data2, sizeof(int));
        printf("read:%d\n", data2);

        close(fd);
        return 0;
}

六、写结构体数组到文件

01 结构体

结构体

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

struct Test
{
        int a;
        char c;
};


int main()
{
        int fd;
        struct Test data={2, 'c'};
        struct Test data2;
        fd = open("./file", O_RDWR);

        //ssize_t write(int fd, const void *buf, size_t count);
        int n_write = write(fd, &data, sizeof(struct Test));

        lseek(fd, 0, SEEK_SET);

        //ssize_t read(int fd, void *buf, size_t count);
        int n_read = read(fd, &data2, sizeof(struct Test));
        printf("read: %d %c\n", data2.a, data2.c);

        close(fd);
        return 0;
}
~              

02 结构体数组

在这里插入图片描述

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

struct Test
{
        int a;
        char c;
};


int main()
{
        int fd;
        struct Test data[2] = {{96, 'a'}, {97, 'b'}};
        struct Test data2[2];
        fd = open("./file", O_RDWR);

        //ssize_t write(int fd, const void *buf, size_t count);
        int n_write = write(fd, &data, sizeof(struct Test)*2);

        lseek(fd, 0, SEEK_SET);

        //ssize_t read(int fd, void *buf, size_t count);
        int n_read = read(fd, &data2, sizeof(struct Test)*2);
        printf("read: %d %c\n", data2[0].a, data2[0].c);
        printf("read: %d %c\n", data2[1].a, data2[1].c);

        close(fd);
        return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值