C 语言实现文件复制功能

文件的复制是常用的功能,要求写一段代码,让用户输入要复制的文件以及新建的文件,然后对文件进行复制。能够复制的文件包括文本文件和二进制文件,你可以复制 1G 的电影,也可以复制 1Byte 的 txt 文档。

实现文件复制的主要思路是:开辟一个缓冲区,不断从原文件中读取内容到缓冲区,每读取完一次就将缓冲区中的内容写入到新建的文件,直到把原文件的内容读取完。

这里有两个关键的问题需要解决:
1) 开辟多大的缓冲区合适?缓冲区过小会造成读写次数的增加,过大也不能明显提高效率。目前大部分磁盘的扇区都是 4K 对齐的,如果读写的数据不是 4K 的整数倍,就会跨扇区读取,降低效率,所以我们开辟 4K 的缓冲区。

2) 缓冲区中的数据是没有结束标志的,如果缓冲区填充不满,如何确定写入的字节数?最好的办法就是每次读取都能返回读取到的字节数。

fread() 的原型为:
size_t fread ( void *ptr, size_t size, size_t count, FILE *fp );
它返回成功读写的块数,该值小于等于 count。如果我们让参数 size 等于 1,那么返回的就是读取的字节数。

注意:fopen() 一定要以二进制的形式打开文件,不能以文本形式打开,否则系统会对文件进行一些处理,如果是文本文件,像 .txt 等,可能没有问题,但如果是其他格式的文件,像 .mp4, .rmvb, .jpg 等,复制后就会出错,无法读取。

代码实现:
#include <stdio.h>
#include <stdlib.h>

int copyFile(char *fileRead, char *fileWrite);

int main(){
    char fileRead[100];  // 要复制的文件名
    char fileWrite[100];  // 复制后的文件名
   
    // 获取用户输入
    printf("要复制的文件:");
    scanf("%s", fileRead);
    printf("将文件复制到:");
    scanf("%s", fileWrite);

    // 进行复制操作
    if( copyFile(fileRead, fileWrite) ){
        printf("恭喜你,文件复制成功!\n");
    }else{
        printf("文件复制失败!\n");
    }

    return 0;
}

/**
* 文件复制函数
* @param    fileRead    要复制的文件
* @param    fileWrite   复制后文件的保存路径
* @return   int         1: 复制成功;2: 复制失败
**/
int copyFile(char *fileRead, char *fileWrite){
    FILE *fpRead;  // 指向要复制的文件
    FILE *fpWrite;  // 指向复制后的文件
    int bufferLen = 1024*4;  // 缓冲区长度
    char *buffer = (char*)malloc(bufferLen);  // 开辟缓存
    int readCount;  // 实际读取的字节数

    if( (fpRead=fopen(fileRead, "rb")) == NULL || (fpWrite=fopen(fileWrite, "wb")) == NULL ){
        printf("Cannot open file, press any key to exit!\n");
        getch();
        exit(1);
    }

    // 不断从fileRead读取内容,放在缓冲区,再将缓冲区的内容写入fileWrite
    while( (readCount=fread(buffer, 1, bufferLen, fpRead)) > 0 ){
        fwrite(buffer, readCount, 1, fpWrite);
    }

    free(buffer);
    fclose(fpRead);
    fclose(fpWrite);

    return 1;
}
运行结果:
要复制的文件:d://1.mp4
将文件复制到:d://2.mp4
恭喜你,文件复制成功!
如果文件不存在,会给出提示,并终止程序:
要复制的文件:d://123.mp4
将文件复制到:d://333.mp4
d://cyuyan.txt: No such file or directory

第 46 行是文件复制的核心代码。通过 fread() 函数,每次从 fileRead 文件中读取 bufferLen 个字节,放到缓冲区,再通过 fwrite() 函数将缓冲区的内容写入 fileWrite 文件。

正常情况下,每次会读取 bufferLen 个字节,即 readCount=bufferLen;如果文件大小不足 bufferLen 个字节,或者读取到文件末尾,实际读取到的字节就会小于 bufferLen,即 readCount<bufferLen。所以通过 fwrite() 写入文件时,应该以 readCount 为准。