文件的复制是常用的功能,要求写一段代码,让用户输入要复制的文件以及新建的文件,然后对文件进行复制。能够复制的文件包括文本文件和二进制文件,你可以复制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等,复制后就会出错,无法读取。

代码实现:


  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int copyFile(char *fileRead, char *fileWrite);
  4. int main(){
  5. char fileRead[100]; // 要复制的文件名
  6. char fileWrite[100]; // 复制后的文件名
  7. // 获取用户输入
  8. printf("要复制的文件:");
  9. scanf("%s", fileRead);
  10. printf("将文件复制到:");
  11. scanf("%s", fileWrite);
  12. // 进行复制操作
  13. if( copyFile(fileRead, fileWrite) ){
  14. printf("恭喜你,文件复制成功!\n");
  15. }else{
  16. printf("文件复制失败!\n");
  17. }
  18. return 0;
  19. }
  20. /**
  21. * 文件复制函数
  22. * @param fileRead 要复制的文件
  23. * @param fileWrite 复制后文件的保存路径
  24. * @return int 1: 复制成功;2: 复制失败
  25. **/
  26. int copyFile(char *fileRead, char *fileWrite){
  27. FILE *fpRead; // 指向要复制的文件
  28. FILE *fpWrite; // 指向复制后的文件
  29. int bufferLen = 1024*4; // 缓冲区长度
  30. char *buffer = (char*)malloc(bufferLen); // 开辟缓存
  31. int readCount; // 实际读取的字节数
  32. if( (fpRead=fopen(fileRead, "rb")) == NULL || (fpWrite=fopen(fileWrite, "wb")) == NULL ){
  33. printf("Cannot open file, press any key to exit!\n");
  34. getch();
  35. exit(1);
  36. }
  37. // 不断从fileRead读取内容,放在缓冲区,再将缓冲区的内容写入fileWrite
  38. while( (readCount=fread(buffer, 1, bufferLen, fpRead)) > 0 ){
  39. fwrite(buffer, readCount, 1, fpWrite);
  40. }
  41. free(buffer);
  42. fclose(fpRead);
  43. fclose(fpWrite);
  44. return 1;
  45. }

运行结果:

要复制的文件: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语言实现文件复制功能(包括文本文件和二进制文件)的更多相关文章

  1. C语言实现文件复制功能(包括文本文件和二进制文件)

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

  2. 【c的文件操作】文本文件和二进制文件(内存映像)的不同 文件结尾判断feof , EOF

    查看 stdio.h 可以看到如下定义: #define  EOF  (-1) #define  _IOEOF  0x0010  #define  feof(_stream)  ((_stream)- ...

  3. C语言之文件操作

    C语言之文件操作 在本节我们将会讲解有关文件的读写操作: 纲要: 一些需要掌握的知识点 文件名 文件类型 数据流 文件缓冲区 文件指针 与文件操作相关的一些函数 文件的打开及关闭 文件的顺序读写 文件 ...

  4. C 语言 .h文件的作用

    C语言头文件的作用 最近在工作当中遇到了一点小问题,关于C语言头文件的应用问题,主要还是关于全局变量的定义和声明问题.学习C语言已经有好几年了,工作使用也近半年了,但是对于这部分的东西的确还没有深入的 ...

  5. 嵌入式C语言头文件的建立与使用

    如何正确编写 C 语言头文件和与之相关联的 c 源程序文件,这首先就要了解它们的各自功能. 要理解 C 文件与头文件(即.h)有什么不同之处,首先需要弄明白编译器的工作过程. 一般说来编译器会做以下几 ...

  6. C语言头文件

    最近在工作当中遇到了一点小问题,关于C语言头文件的应用问题,主要还是关于全局变量的定义和声明问题.学习C语言已经有好几年了,工作使用也近半年了,但是对于这部分的东西的确还没有深入的思考过.概念上还是比 ...

  7. C语言对文件的操作函数用法详解1

    在ANSIC中,对文件的操作分为两种方式,即: 流式文件操作 I/O文件操作 一.流式文件操作 这种方式的文件操作有一个重要的结构FILE,FILE在stdio.h中定义如下: typedef str ...

  8. 配置文件格式用哪个?文件夹+纯文本文件,XML,SQLite

    稍具规模的软件都会须要一个配置文件来支持软件的执行.眼下常见的配置文件格式有纯文本.XML.SQLite.自己定义二进制格式,怎样进行选择呢? 1 纯文本--永远不会失效的文件格式 文本化是传统Uni ...

  9. C语言之文件操作08——总结

    C程序的文件操作共涵盖7个例题,包括格式打印,文件读取,条件查找,矩阵的文件操作,数据格式输入及调用计算等内容. 文件操作使得程序有更强的拓展性,使其能够单独保存数据.这为程序的调试和优化打下了坚实的 ...

随机推荐

  1. Linux为grub菜单加密码

    为grub菜单加密码 加入密码后,再次进入单用户或者给下次管理grub需要输入密码 加密操作 /sbin/grub-md5-crypt # 之后输入2次密码会生成加密后字符串 编辑grub加载文件 v ...

  2. QuickBI助你成为分析师-数据建模(二)

    摘要: 数据集编辑功能界面介绍以及常见问题总结. 在数据集编辑界面可以进行数据建模来更好的展示数据,创建数据集默认将数值类型字段作为度量,日期.字符串等类型作为维度,度量可以根据维度分组展示.下面来介 ...

  3. 《C++ Primer Plus》读书笔记之十二—C++中的代码重用

    第14章 C++中的代码重用 1.C++代码重用方法:公有继承.使用本身是另一个类的对象的类成员(这种方法称为包含.组合或层次化).私有或保护继承.类模板等. 2.模板特性意味着声明对象时,必须指定具 ...

  4. Android点击事件

    Android点击事件 备注 全局实现View.OnClickListener 或许需要将MainActivity设置为public 注册事件 btn_login.setOnClickListener ...

  5. Centos7+Mysql80安装+远程链接开启

    CentOS7安装mysql80 下载repo源 在xshell运行命令 # wget http://repo.mysql.com/mysql80-community-release-el7.rpm ...

  6. ZT Android4.2蓝牙基础架构学习

    Android4.2蓝牙基础架构学习 分类: Jellybean Bluetooth Bluetooth 2013-10-13 23:58 863人阅读 评论(3) 收藏 举报 androidblue ...

  7. CGI编程学习

    @CGI编程学习 目录(?)[+] 一.基本原理 CGI:通用网关接口(Common Gateway Interface)是一个Web服务器主机提供信息服务的标准接口.通过CGI接口,Web服务器就能 ...

  8. HBase学习之路 (四)HBase的API操作

    Eclipse环境搭建 具体的jar的引入方式可以参考http://www.cnblogs.com/qingyunzong/p/8623309.html HBase API操作表和数据 import ...

  9. linq to sql 中增删改查

    首先我先说一下,如果真的要用linq做项目的话,也会是比较方便的.已经尝试了在三层架构中应用linq to sql 比较方便. //有三个不同的数据库表,所以写法不一样 public class Li ...

  10. [图解tensorflow源码] [转载] tensorflow设备内存分配算法解析 (BFC算法)

    转载自 http://weibo.com/p/1001603980563068394770   @ICT_吴林阳 tensorflow设备内存管理模块实现了一个best-fit with coales ...