128 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为准。
128 C语言实现文件复制功能(包括文本文件和二进制文件)的更多相关文章
- C语言实现文件复制功能(包括文本文件和二进制文件)
文件的复制是常用的功能,要求写一段代码,让用户输入要复制的文件以及新建的文件,然后对文件进行复制.能够复制的文件包括文本文件和二进制文件,你可以复制1G的电影,也可以复制1Byte的txt文档. 实现 ...
- 【c的文件操作】文本文件和二进制文件(内存映像)的不同 文件结尾判断feof , EOF
查看 stdio.h 可以看到如下定义: #define EOF (-1) #define _IOEOF 0x0010 #define feof(_stream) ((_stream)- ...
- C语言之文件操作
C语言之文件操作 在本节我们将会讲解有关文件的读写操作: 纲要: 一些需要掌握的知识点 文件名 文件类型 数据流 文件缓冲区 文件指针 与文件操作相关的一些函数 文件的打开及关闭 文件的顺序读写 文件 ...
- C 语言 .h文件的作用
C语言头文件的作用 最近在工作当中遇到了一点小问题,关于C语言头文件的应用问题,主要还是关于全局变量的定义和声明问题.学习C语言已经有好几年了,工作使用也近半年了,但是对于这部分的东西的确还没有深入的 ...
- 嵌入式C语言头文件的建立与使用
如何正确编写 C 语言头文件和与之相关联的 c 源程序文件,这首先就要了解它们的各自功能. 要理解 C 文件与头文件(即.h)有什么不同之处,首先需要弄明白编译器的工作过程. 一般说来编译器会做以下几 ...
- C语言头文件
最近在工作当中遇到了一点小问题,关于C语言头文件的应用问题,主要还是关于全局变量的定义和声明问题.学习C语言已经有好几年了,工作使用也近半年了,但是对于这部分的东西的确还没有深入的思考过.概念上还是比 ...
- C语言对文件的操作函数用法详解1
在ANSIC中,对文件的操作分为两种方式,即: 流式文件操作 I/O文件操作 一.流式文件操作 这种方式的文件操作有一个重要的结构FILE,FILE在stdio.h中定义如下: typedef str ...
- 配置文件格式用哪个?文件夹+纯文本文件,XML,SQLite
稍具规模的软件都会须要一个配置文件来支持软件的执行.眼下常见的配置文件格式有纯文本.XML.SQLite.自己定义二进制格式,怎样进行选择呢? 1 纯文本--永远不会失效的文件格式 文本化是传统Uni ...
- C语言之文件操作08——总结
C程序的文件操作共涵盖7个例题,包括格式打印,文件读取,条件查找,矩阵的文件操作,数据格式输入及调用计算等内容. 文件操作使得程序有更强的拓展性,使其能够单独保存数据.这为程序的调试和优化打下了坚实的 ...
随机推荐
- 远程计算机 进程/服务 启动停止(WMI)
WMI的远程管理需要其计算机的本地管理员组权限,例:gwmi win32_computersystem -computer win08r2d #在远程计算机上启动 notepad.exe 进程invo ...
- Linux mount命令详解
mount命令用于加载文件系统到指定的加载点.此命令的也常用于挂载cdrom,使我们可以访问cdrom中的数据,因为你将光盘插入cdrom中,Linux并不会自动挂载,必须使用Linux mount命 ...
- 解决linux buffer/cache 消耗内存过高引发的问题
工作中接到DBA报障某台服务器 跑一些大的数据,服务器就无法远程连接,报错,抓过日志叫DELL工程师检测也没问题,系统也重装过, 现在些一些较大的数据就会报如 图错误,由于服务器远在异地城市IDC机房 ...
- 如何创建一个Quartz.NET的工作,需要注射autofac
问题: 使用 Quartz.Net 做定时任务时,实现IJob对象的服务,Autofac不会自动注入,使用构造函数会直接出现异常,无法执行Execute方法. 解决方式 方法一: 使用 Autofac ...
- 列表 ->join---> 字符串 转类型:x--->y类型 y(x)
列表 ->join---> 字符串 转类型:x--->y类型 y(x)
- 面对对象程序设计_task2_1001.A+B Format (20)
Someting about 1001.A+B Format (20) 问题描述及我所写的代码:click here → My Task 看到这个题目的时候,我的想法很简单,直接判断直接输出,因为给定 ...
- 对于socket发送数据时是否要加锁及write read的阻塞非阻塞
偶尔讨论到了socket发送数据时是否应该加锁的问题,就在网上查了一下,下面是大神陈硕的答案 对于 UDP,多线程读写同一个 socket 不用加锁,不过更好的做法是每个线程有自己的 socket,避 ...
- Spark系列-核心概念
Spark系列-初体验(数据准备篇) Spark系列-核心概念 一. Spark核心概念 Master,也就是架构图中的Cluster Manager.Spark的Master和Workder节点分别 ...
- UVa 1393 - Highways(数论)
链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...
- Js 中的事件委托/事件代理
什么叫事件委托/事件代理呢 ? JavaScript高级程序设计上讲:事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件. 事件冒泡: 当事件发生后,这个事件就要开始传 ...