我们平时所见的文件,例如 txt、doc、mp4 等,文件内容是按照从头到尾的顺序依次存储在磁盘上的,就像排起一条长长的队伍,称为顺序文件

除了顺序文件,还有索引文件、散列文件等,一般用于特殊领域,例如数据库、高效文件系统等。

顺序文件的存储结构决定了它能够高效读取内容,但不能够随意插入、删除和修改内容。例如在文件开头插入100个字节的数据,那么原来文件的所有内容都要向后移动100个字节,这不仅是非常低效的操作,而且还可能覆盖其他文件。因此C语言没有提供插入、删除、修改文件内容的函数,要想实现这些功能,只能自己编写函数。

以插入数据为例,假设原来文件的大小为 1000 字节,现在要求在500字节处插入用户输入的字符串,那么可以这样来实现:
1) 创建一个临时文件,将后面500字节的内容复制到临时文件;
2) 将原来文件的内部指针调整到500字节处,写入字符串;
3) 再将临时文件中的内容写入到原来的文件(假设字符串的长度为100,那么此时文件内部指针在600字节处)。

删除数据时,也是类似的思路。假设原来文件大小为1000字节,名称为 demo.mp4,现在要求在500字节处往后删除100字节的数据,那么可以这样来实现:
1) 创建一个临时文件,先将前500字节的数据复制到临时文件,再将600字节之后的所有内容复制到临时文件;
2) 删除原来的文件,并创建一个新文件,命名为 demo.mp4;
3) 将临时文件中的所有数据复制到 demo.mp4。

修改数据时,如果新数据和旧数据长度相同,那么设置好内部指针,直接写入即可;如果新数据比旧数据长,相当于增加新内容,思路和插入数据类似;如果新数据比旧数据短,相当于减少内容,思路和删除数据类似。实际开发中,我们往往会保持新旧数据长度一致,以减少编程的工作量,所以我们不再讨论新旧数据长度不同的情况。

总起来说,本节重点讨论数据的插入和删除。

文件复制函数

在数据的插入删除过程中,需要多次复制文件内容,我们有必要将该功能实现为一个函数,如下所示:

/*** 文件复制函数* @param  fSource       要复制的原文件* @param  offsetSource  原文件的位置偏移(相对文件开头),也就是从哪里开始复制* @param  len           要复制的内容长度,小于0表示复制offsetSource后边的所有内容* @param  fTarget       目标文件,也就是将文件复制到哪里* @param  offsetTarget  目标文件的位置偏移,也就是复制到目标文件的什么位置* @return  成功复制的字节数
**/
long fcopy(FILE *fSource, long offsetSource, long len, FILE *fTarget, long offsetTarget){int bufferLen = 1024*4;  // 缓冲区长度char *buffer = (char*)malloc(bufferLen);  // 开辟缓存int readCount;  // 每次调用fread()读取的字节数long nBytes = 0;  //总共复制了多少个字节int n = 0;  //需要调用多少次fread()函数int i;  //循环控制变量fseek(fSource, offsetSource, SEEK_SET);fseek(fTarget, offsetTarget, SEEK_SET);if(len<0){  //复制所有内容while( (readCount=fread(buffer, 1, bufferLen, fSource)) > 0 ){nBytes += readCount;fwrite(buffer, readCount, 1, fTarget);}}else{  //复制len个字节的内容n = (int)ceil((double)((double)len/bufferLen));for(i=1; i<=n; i++){if(len-nBytes < bufferLen){ bufferLen = len-nBytes; }readCount = fread(buffer, 1, bufferLen, fSource);fwrite(buffer, readCount, 1, fTarget);nBytes += readCount;}}fflush(fTarget);free(buffer);return nBytes;
}

该函数可以将原文件任意位置的任意长度的内容复制到目标文件的任意位置,非常灵活。如果希望实现《C语言实现文件复制功能(包括文本文件和二进制文件)》一节中的功能,那么可以像这面这样调用:

fcopy(fSource, 0, -1, fTarget, 0);

文件内容插入函数

请先看代码:

/*** 向文件中插入内容* @param  fp      要插入内容的文件* @param  buffer  缓冲区,也就是要插入的内容* @param  offset  偏移量(相对文件开头),也就是从哪里开始插入* @param  len     要插入的内容长度* @return  成功插入的字节数
**/
int finsert(FILE *fp, long offset, void *buffer, int len){long fileSize = fsize(fp);FILE *fpTemp;  //临时文件if(offset>fileSize || offset<0 || len<0){  //插入错误return -1;}if(offset == fileSize){  //在文件末尾插入fseek(fp, offset, SEEK_SET);if(!fwrite(buffer, len, 1, fp)){return -1;}}if(offset < fileSize){  //从开头或者中间位置插入fpTemp = tmpfile();fcopy(fp, 0, offset, fpTemp, 0);fwrite(buffer, len, 1, fpTemp);fcopy(fp, offset, -1, fpTemp, offset+len);freopen(FILENAME, "wb+", fp );fcopy(fpTemp, 0, -1, fp, 0);fclose(fpTemp);}return 0;
}

代码说明:
1) fsize() 是在《C语言获取文件大小(长度)》自定义的函数,用来获取文件大小(以字节计)。

2) 第17行判断数据的插入位置,如果是在文件末尾,就非常简单了,直接用 fwrite() 写入即可。

3) 如果从文件开头或中间插入,就得创建临时文件。

tmpfile() 函数用来创建一个临时的二进制文件,可以读取和写入数据,相当于 fopen() 函数以"wb+"方式打开文件。该临时文件不会和当前已存在的任何文件重名,并且会在调用 fclose() 后或程序结束后自动删除。

文件内容删除函数

请看下面的代码:

int fdelete(FILE *fp, long offset, int len){long fileSize = getFileSize(fp);FILE *fpTemp;if(offset>fileSize || offset<0 || len<0){  //错误return -1;}fpTemp = tmpfile();fcopy(fp, 0, offset, fpTemp, 0);  //将前offset字节的数据复制到临时文件fcopy(fp, offset+len, -1, fpTemp, offset);  //将offset+len之后的所有内容都复制到临时文件freopen(FILENAME, "wb+", fp );  //重新打开文件fcopy(fpTemp, 0, -1, fp, 0);fclose(fpTemp);return 0;
}

文件第5~7行用来判断传入的参数是否合法。freopen() 以"w+"方式打开文件时,如果有同名的文件存在,那么先将文件内容删除,作为一个新文件对待。

第十一章 文件操作_C语言插入、删除、更改文件内容相关推荐

  1. 第十一章 文件操作_C语言fopen函数的用法,C语言打开文件详解

    在C语言中,操作文件之前必须先打开文件:所谓"打开文件",就是让程序和文件建立连接的过程. 打开文件之后,程序可以得到文件的相关信息,例如大小.类型.权限.创建者.更新时间等.在后 ...

  2. 第十一章 文件操作_C语言实现文件复制功能(包括文本文件和二进制文件)

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

  3. 第十一章 文件操作_C语言fscanf和fprintf函数的用法详解(格式化读写文件)

    fscanf() 和 fprintf() 函数与前面使用的 scanf() 和 printf() 功能相似,都是格式化读写函数,两者的区别在于 fscanf() 和 fprintf() 的读写对象不是 ...

  4. 【C 语言】文件操作 ( 学生管理系统 | 插入数据 | 查询数据 | 删除数据 )

    文章目录 一.学生管理系统 1.插入数据 2.查询数据 3.删除数据 二.完整代码 一.学生管理系统 实现一个简易学生管理系统 , 验证文件操作 ; 1.插入数据 从命令行接收数据 , 放入结构体成员 ...

  5. c语言创造的文件保存路径_c语言怎么把变量写入文件路径

    1. c语言 如何将变量写入文件 比如写入 c盘下面的test.txt文件中. #include #include void main(void) { char achBuf[256]; memset ...

  6. java 删 除文件操作,C语言 File文件处理 删除文件

    1.删除文件 要使用C语言删除文件,需要使用int remove(char *filename);方法,filename为要删除的文件名,可以为一目录.如果参数filename 为一文件,则调用unl ...

  7. AIR文件操作(三):使用FileStream对象读写文件

    快速上手例: 例1.读xml var testXML:XML; var file:File = File.documentsDirectory.resolvePath("Mousebomb/ ...

  8. python 文件操作不被打断_python学习六文件操作和异常处理

    1.文件的定义和类型 什么是文件呢? 文件是数据的抽象和集合 文件是存储在辅助存储器上的数据序列 文件是存储的一种 文件有哪些类型呢? 本质上所有文件以二进制储存,不过又可以分为文本文件和二进制文件 ...

  9. python引入文件并执行_文件操作和导入os模块执行文件和目录管理操作

    文件概念以及文本文件和二进制文件的区别 计算机的CPU如果想要访问保存在磁盘上的文件,第一步需要把磁盘上的文件数据加载到内存中.因为内存的读写速度要比磁盘的读写速度快很多. 计算机只能识别0101这种 ...

最新文章

  1. 给AI一张高清照片,分分钟还你细节满满的3D人体模型,GitHub标星3.6k | 在线可玩...
  2. 百行代码打造一个DI容器(支持瞬时生命周期、单利生命周期、构造函数自动注入、属性自动注入、字段自动注入)...
  3. winform 系统托盘程序
  4. 静态切割窗体+关联对话框
  5. BZOJ3747: [POI2015]Kinoman
  6. eclipse中server location为灰色,不能修改
  7. 通过调用外部exe的方法实现c#调用java
  8. 商务高端、CPU要求高-笔记本选型
  9. Windows核心编程_窗口透明组件不透明
  10. Raki的读paper小记:BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding
  11. 机器学习——鸢尾花数据集
  12. 张量分解--非负矩阵分解 (NMF)
  13. GitHub图片加载不出来解决方案(超详细图文教程)
  14. 车联网平台介绍(一)
  15. HackTheBox::Optimum
  16. java将异常写到text,java捕获异常信息存入txt文件示例
  17. Verilog语法-模块module[Day2学习笔记]
  18. jsp房屋交易管理系统
  19. 推送跳转到对应的详情页(使用友盟推送的方式)
  20. Generating SSH2 ECDSA host key:[FAILED]

热门文章

  1. 使用一个SQL查询出每门课程的成绩都大于80分的学生姓名
  2. 项目集成腾讯移动直播总结--后端
  3. TCL发布两款可穿戴设备;中兴通讯推出第三代5G室内路由器;绘王联合制作《河岸》获棕榈泉国际短片电影节最佳动画奖 | 全球TMT...
  4. ChatGPT电脑版安装下载
  5. 微信小程序(7)说说微信小程序的发布流程?
  6. 气象接口返回图标_国家气象局提供的天气预报接口及使用说明
  7. 镭速-文件传输数据实时对比!一秒将传输速度提升100倍
  8. hdu 杭电1429 胜利大逃亡(续)
  9. 网站建设凸显效果的配色原则
  10. 程序员,停止你的焦虑