本文主要向大家介绍了如何用C语言实现文件复制功能(包括文本文件和二进制文件),通过具体的内容向大家展示,希望对大家学习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>
intcopyFile(char*fileRead,char*fileWrite);
intmain()
{
charfileRead[100];// 要复制的文件名
charfileWrite[100];// 复制后的文件名
// 获取用户输入
printf("要复制的文件:");
scanf("%s",fileRead);
printf("将文件复制到:");
scanf("%s",fileWrite);
// 进行复制操作
if(copyFile(fileRead,fileWrite))
{
printf("恭喜你,文件复制成功!\n");
}else{
printf("文件复制失败!\n");
}
return0;
}
/**
* 文件复制函数
*@paramfileRead 要复制的文件
*@paramfileWrite 复制后文件的保存路径
*@returnint 1: 复制成功;2: 复制失败
**/
intcopyFile(char*fileRead,char*fileWrite)
{
FILE*fpRead;// 指向要复制的文件
FILE*fpWrite;// 指向复制后的文件
intbufferLen=1024*4;// 缓冲区长度
char*buffer=(char*)malloc(bufferLen);// 开辟缓存
intreadCount;// 实际读取的字节数
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);
return1;
}
运行结果:
要复制的文件:d://1.mp4
将文件复制到:d://2.mp4
恭喜你,文件复制成功!
如果文件不存在,会给出提示,并终止程序:
要复制的文件:d://123.mp4
将文件复制到:d://333.mp4
d://cyuyan.txt: No such file or directory
while((readCount=fread(buffer,1,bufferLen,fpRead))>0)是文件复制的核心代码。通过fread()函数,每次从 fileRead 文件中读取 bufferLen 个字节,放到缓冲区,再通过fwrite()函数将缓冲区的内容写入fileWrite文件。
正常情况下,每次会读取bufferLen个字节,即readCount=bufferLen;如果文件大小不足bufferLen个字节,或者读取到文件末尾,实际读取到的字节就会小于bufferLen,即readCount<bufferLen。所以通过fwrite()写入文件时,应该以readCount为准。
可以用write或者fwrite,这两个函数用法相似度极高;
函数原型如下:
ssize_t write(int fd, const void *buf, size_t count);
ssize_t read(int fd, void *buf, size_t count);
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
read/fread返回值:读普通文件时的返回值为读到的字节或者块数,读到末尾则返回0
1、文本复制 fgetc、fputc函数实现
#include <stdio.h>
int main(void)
{
int ch;
FILE *sfp;
FILE *dfp;
char sfilename[FILENAME_MAX];
char dfilename[FILENAME_MAX];
printf("source filename: "); scanf("%s", sfilename);
printf("destination filename: "); scanf("%s", dfilename);
if((sfp = fopen(sfilename, "r")) == NULL)
{
printf("\aSource file open failed.\n");
}
else
{
if((dfp = fopen(dfilename, "w")) == NULL)
{
printf("\aDestinatiom file open failed.\n");
}
else
{
while((ch = fgetc(sfp)) != EOF)
fputc(ch, dfp);
fclose(dfp);
}
fclose(sfp);
}
return 0;
}
2、二进制复制、使用fread、fwrite函数实现
#include <stdio.h>
int main(void)
{
int ch;
FILE *sfp;
FILE *dfp;
char sfilename[FILENAME_MAX];
char dfilename[FILENAME_MAX];
printf("Source filename: "); scanf("%s", sfilename);
printf("Destination filename: "); scanf("%s", dfilename);
if((sfp = fopen(sfilename, "rb")) == NULL)
{
printf("\aSource file open failed.\n");
}
else
{
if((dfp = fopen(dfilename, "wb")) == NULL)
{
printf("\aDestination file open failed.\n");
}
else
{
int n;
while(n = (fread(&ch, sizeof(int), 1, sfp)) > 0)
fwrite(&ch, sizeof(int), 1, dfp);
fclose(dfp);
}
fclose(sfp);
}
return 0;
}