用Linux系统调用函数实现file1添加式复制到file2尾部和file1覆盖式复制到file3

1、背景介绍

将文件1的内容复制到文件2和文件3中;对于文件2,每次复制把文件1内容添加到文件2尾(保留文件2原有内容);
对于文件3,每次复制用文件1内容覆盖文件3原有内容(不保留文件3原有内容)。

2、代码实现

// printf()函数、perror()函数所需的头文件。  
#include <stdio.h>  
// open()函数所需的头文件。  
#include <sys/types.h>  
#include <sys/stat.h>  
#include <fcntl.h>  
// close()函数所需的头文件。  
#include <unistd.h>  
// strcmp()函数和memset()函数的头文件。  
#include <string.h>  
  
  
// 至少有两个参数至main函数:argc和argv,  
// 第一个是提供给main函数的参数个数,  
// 第二个是参数的字符串数组的指针。  
// argc: 整数,用来统计你运行程序时送给main函数的命令行参数的个数。本例中argc为4。  
// argv[]: 指针数组,用来存放指向你的字符串参数的指针,每一个元素指向一个参数。  
// argv[0] 指向程序运行的全路径名,本例中为./hello。  
// argv[1] 指向在dos命令行中执行程序名后的第一个字符串,本例中为file1。  
// argv[2] 指向执行程序名后的第二个字符串,本例中为file2。  
// argv[3] 指向执行程序名后的第三个字符串,本例中为file3。  
int main(int argc, char *argv[])  
{  
    // 如果命令行参数的个数为4(即./hello、file1、file2、file3这4个参数),  
    // 并且执行程序名后的第一个字符串和第二个字符串不相等(即file1和file2不相等),  
    // 第二个字符串和第三个字符串不相等(即file2和file3不相等),则进行后续复制文件操作。  
    if((argc == 4) && (strcmp(argv[1], argv[2]) != 0) &&(strcmp(argv[1], argv[3]) != 0))  
    {  
  
        // 定义int类型的变量fd_src,fd_dest1,fd_dest2,ret,  
        // fd_src,fd_dest1,fd_dest2用来接收open()函数的返回值。  
        // ret用来接收read()函数的返回值。  
        // fd_src用来接收用open()函数打开file1的返回值。  
        // fd_dest1用来接收用open()函数打开file2的返回值。  
        // fd_dest2用来接收用open()函数打开file3的返回值。  
        int fd_src, fd_dest1,fd_dest2,ret;  
       
        // 以只读的方式打开执行程序名后第一个字符串所表示的文件(即file1)。  
        fd_src = open(argv[1], O_RDONLY);  
        // 如果返回值小于0,即表明打开文件失败。  
        if(fd_src < 0)  
        {  
            // perror(s)函数用来将上一个函数发生错误的原因输出到标准设备,  
            // 参数s所指的字符串会先打印出,后面再加上错误原因字符串。  
            perror("open argv[1]");  
            // 返回-1,结束程序。  
            return -1;  
        }  

        // 以只写并追加的方式【如果原来文件里面有内容,则这次写入会写在文件的最末尾】  
        // 打开执行程序名后第二个字符串所表示的文件(即file2)。  
        fd_dest1 = open(argv[2], O_WRONLY|O_APPEND);  
        // 如果返回值小于0,则表明打开文件失败。  
        if(fd_dest1 < 0)  
        {  
            // 关闭执行程序名后第一个字符串所表示的文件(即file1)。  
            close(fd_src);  
            // perror(s)函数用来将上一个函数发生错误的原因输出到标准设备,  
            // 参数s所指的字符串会先打印出,后面再加上错误原因字符串。  
            perror("open argv[2]");  
            // 返回-1,结束程序。  
            return -1;  
        }  

         // 以只写并创建的方式打开执行程序名后第三个字符串所表示的文件(即file3)。  
        // 如果原来这个文件存在则会重新创建这个文件,原来的内容会被消除掉。
        //(有点类似于先删除原来的文件再创建一个新的)  
        // 0644表示设置文件访问权限的初始值,0644应该是rw-r--r--,  
        // 即用户:可读可写、用户组: 可读、其他:可读。  
        fd_dest2 = open(argv[3], O_WRONLY|O_CREAT, 0644);  
        // 如果返回值小于0,则表明打开文件失败。  
        if(fd_dest2 < 0)  
        {  
            // 关闭执行程序名后第一个字符串所表示的文件(即file1)。  
            close(fd_src);  
            // perror(s)函数用来将上一个函数发生错误的原因输出到标准设备,  
            // 参数s所指的字符串会先打印出,后面再加上错误原因字符串。  
            perror("open argv[3]");  
            // 返回-1,结束程序。  
            return -1;  
        }  

        // 定义一个大小为1024个字节的字符数组,命名为buf。  
        char buf[1024] ="";  
        // 用do-while循环进行文件的复制操作。  
        do  
        {  
            // memset()函数把buf中所有字节都换作字符“0”,即对字符数组进行初始化操作。  
            memset(buf,0,sizeof(buf));  
            // read()函数会从fd_src所指的文件中传送大小为sizeof(buf)个字节的数据
            //给buf指针所指的内存中。  
            // read()函数的返回值为实际读取到的字节数。  
            // 如果返回0, 表示已到达文件尾或是无可读取的数据。  
            ret = read(fd_src, buf, sizeof(buf));  
            // 如果read()函数实际读取到的字节数大于0,  
            // 则用write()函数把buf所指的内存写ret个字节到fd_dest1和fd_dest2所指的文件内。  
            if(ret>0){
            printf("开始执行将文件file1的内容复制到文件file2的末尾!\n");  
            write(fd_dest1, buf, ret); 
            printf("将文件file1的内容复制到文件file2的末尾操作成功!\n");  
            printf("*********************************************\n");  
            printf("开始执行将文件file1的内容覆盖文件file3!\n"); 
            write(fd_dest2, buf, ret); 
            printf("将文件file1的内容覆盖文件file3的内容操作成功!\n");  
            }
        }while(ret >0);  
        //close()函数关闭file1。  
        close(fd_src);  
        //close()函数关闭file2。  
        close(fd_dest1);   
        //close()函数关闭file3。  
        close(fd_dest2);   
    }  
    // 程序结束。  
    return 0;  
}  
上一篇:修改vue的配置项支持生产环境下二级域名访问的方法


下一篇:Linux文件编程--简单应用