Linux学习-文件IOA1——用结构体和文件操作函数实现文件的拷贝

Linux学习-文件IOA1——用结构体和文件操作函数实现文件的拷贝

其实我们不必选用结构体去实现模仿拷贝功能的,但是为了锻炼我们的思维以及对结构体、文件操作函数的使用,所以我们就这样来折腾自己。
学习的过程就是将复杂的事情简单化,再将简单的事情复杂化,这样才会对只是理解更深刻透彻,运用的也会更加得心应手,我们在实际上遇到问题的时候也能从不同角度考虑问题了。(后面的注意事项要看,不然使用方法错误会浪费时间)
以下是参考代码以及注释:

 #include<sys/types.h>//open头文件
#include<sys/stat.h>//open头文件
#include<fcntl.h>//open头文件
#include<unistd.h>//write、read、close头文件
#include<stdio.h>
#include<string.h>
#include<errno.h>//perror头文件
#include<stdlib.h>//memset头文件

#define ERROR    -1            //宏定义-1的值
#define ERROR_P  ((P_FI)ERROR) //为了方便Open_Function函数的返回值
#define SUCCESS  0             //宏定义0的值

typedef struct file_information{
    int open_a_fd;//文件a的描述符
    int open_b_fd;//文件b的描述符
    int write_num;//每次读取文件的大小
    char *pointer_a;//文件a的路径地址
    char *pointer_b;//文件b的路径地址
}FI,*P_FI;//定义结构体类型

//-----初始化以及打开文件函数的定义-------------------------------------
P_FI Open_Function(char *argv_1,char *argv_2);

//-----写入文件数据函数的定义-------------------------------------------
int Write_Function(P_FI type);

//-----关闭释放文件空间函数的定义---------------------------------------
int Close_Function(P_FI type);

//-----初始化以及打开文件函数-------------------------------------------
P_FI Open_Function(char *argv_1,char *argv_2)
{
    //-------初始化内存空间-----------------------------------
    //给结构体opinter_strcut申请内存
    P_FI opinter_strcut = (P_FI)malloc(sizeof(FI));
    //判断是否成功,要养成良好的习惯,即使以后用不到,也要培养这个思维
    if(opinter_strcut == NULL)
    {
        printf("malloc opinter_struct");
    }
    //初始化,清空内存里面的乐色数据,防止数据乱码情况发生
    memset(opinter_strcut,0,sizeof(FI));
    
    //给pointer_a申请空间,存放路径地址
    opinter_strcut->pointer_a = (char *)malloc(sizeof(*argv_1));
    //判断是否成功,要养成良好的习惯,即使以后用不到,也要培养这个思维
    if(opinter_strcut->pointer_a == NULL)
    {
        perror("malloc pointer_a");
        //返回一个错误时候的指针,我们将-1强制类型转化,上面有宏定义
        return ERROR_P;
    }

    //给pointer_b申请空间,存放路径地址
    opinter_strcut->pointer_b = (char *)malloc(sizeof(*argv_2));
    //判断是否成功,要养成良好的习惯,即使以后用不到,也要培养这个思维
    if(opinter_strcut->pointer_b == NULL)
    {
        perror("malloc pointer_b");
        //返回一个错误时候的指针,我们将-1强制类型转化,上面有宏定义
        return ERROR_P;
    }
    //初始化,清空内存里面的乐色数据,防止数据乱码情况发生
    memset(opinter_strcut->pointer_a,0,sizeof(*argv_1));
    //初始化,清空内存里面的乐色数据,防止数据乱码情况发生
    memset(opinter_strcut->pointer_b,0,sizeof(*argv_2));

    //------打开文件,并且赋值到结构体里面----------------------
    //初始化掩码,防止后面给权限的时候出错
    umask(0000);
    //打开文件a,并把文件描述符赋值到结构体对应的变量open_a_fd
    opinter_strcut->open_a_fd = open(argv_1,O_RDONLY);
    //打开文件b,并把文件描述符赋值到结构体对应的变量open_b_fd
    opinter_strcut->open_b_fd = open(argv_2,O_WRONLY | O_CREAT,0777);
    //定义每次读取的数据大小,赋值给结构体变量write_num
    opinter_strcut->write_num = 20;
    //函数返回值,返回一个指针
    return opinter_strcut;
}

//-----写入文件数据函数的定义-------------------------------------------
int Write_Function(P_FI type)
{
    //-----定义空间作为读取数据的缓存区------------------------
    char array[type->write_num];
    //定义两个变量接受read和write的返回值,在while外面定义就不用每次循环都申请一次
    //优化了程序运行
    int read_ret,write_ret;
    //循环读取数据,写入数据
    while(1)
    {
        //初始化,清空上一次的数据,防止上一次的数据残留会使新数据出现乱码
        memset(array,0,sizeof(type->write_num));
        //读文件a,read_ret接收返回值,进行判断是否成功
        read_ret = read(type->open_a_fd,array,type->write_num);
        //判断是否成功
        //情况1:当返回值是-1时,说明read失败,退出;
        if(read_ret == ERROR)
        {
            perror("read a");
            return ERROR;
        }
        //情况2:当返回值是0的时候,说明已经读取完、写完数据,退出;
        else if(read_ret == SUCCESS)
        {
            printf("文件读取完成!\n");
            return SUCCESS;
        }
        else
        //情况3:说明read还在读取数据,你们玩吗就马上将读取的数据写入文件b里面
        {
            //写入文件b,write_ret接收返回值,进行判断是否成功
            write_ret = write(type->open_b_fd,array,read_ret);
            //判断是否成功,要养成良好的习惯,即使以后用不到,也要培养这个思维
            if(write_ret == ERROR)
            {
                perror("write");
                return ERROR;
            }
        }
    }
}

//-----关闭释放文件空间函数---------------------------------------------
int Close_Function(P_FI type)
{
    //关闭文件a
    int close_ret_a = close(type->open_a_fd);
    //判断是否成功,要养成良好的习惯,即使以后用不到,也要培养这个思维
    if(close_ret_a == ERROR)
    {
        perror("close a");
    }
    //关闭文件b
    int close_ret_b = close(type->open_b_fd);
    //判断是否成功,要养成良好的习惯,即使以后用不到,也要培养这个思维
    if(close_ret_b == ERROR)
    {
        perror("close b");
    }
    //释放结构体里面open_a_fd申请的空间,
    //不能先释放结构体的内存,因为这样做的话我们会找不到open_a_fd的位置;
    free(type->pointer_a);
    //释放结构体里面open_b_fd申请的空间,
    //不能先释放结构体的内存,因为这样做的话我们会找不到open_b_fd的位置;
    free(type->pointer_a);
    //最后再释放结构体。
    free(type);

    return  SUCCESS;
}

//-----主函数----------------------------------------------------------
int main(int argc,char *argv[])
{
    //-----初始化以及打开文件函数的调用----------------------------------
    P_FI open_p = Open_Function(argv[1],argv[2]);
    //判断是否成功
    if(open_p == ERROR_P)
    {
        printf("打开文件失败!\n");
        return ERROR;
    }

    //-----写入文件数据函数的调用---------------------------------------
    int write_ret = Write_Function(open_p);
    //判断是否成功
    if(write_ret == ERROR)
    {
        printf("写入文件失败!\n");
        return ERROR;
    }

    //-----关闭释放文件空间函数的调用-------------------------------------
    Close_Function(open_p);
    //主函数返回值
    return SUCCESS;
}

注意:这样写我们运行的时候不是./文件名 哦,是./文件名 要被拷贝的文件名 拷贝到文件的文件名。例如我要将a.txt的数据拷贝到b.txt,在main文件上执行,那么我的运行命令格式就是:./main a.txt b.txt

代码略长。加油小白菜!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值