目录

  • 思路分析
    • 目的
    • 算法流程
  • 几个需要注意的点
    • 所用的函数
    • 二进制模式与文本模式
    • fseek的坑
  • 源码
  • 结语

思路分析

目的

希望能将给定txt文件的最后一行(无论是空行还是第一行)删掉,并直接保存,而不是另存为某个新的txt文件。

例1:

原文件:
1234567
abcdefg
处理后:
1234567

例2:

原文件:
Hello World!处理后:
Hello World!

例3:

原文件:
This is an example.
处理后

算法流程

大体思路如下:

  1. 以只读方式打开原文件。
  2. 以只写方式打开一个临时文件。
  3. 通过从原文件末尾向前查找换行符的方式确定最后一行的位置。
  4. 从原文件开头逐个读取字符,写入临时文件,直到第3步中确定的位置。
  5. 关闭文件,保存。
  6. 将原文件删除,将临时文件重命名为原文件的名称。

注:本文只用C语言实现,没有C++的内容。

几个需要注意的点

所用的函数

基本上就这几个:

errno_t __cdecl fopen_s(FILE **_Stream, const char *_FileName, const char *_Mode)
int __cdecl fseek(FILE *_Stream, long _Offset, int _Origin)
  • fgetc& fputc& fclose& ftell
  • remove& rename

具体用法看后面的源码吧,都不难,这里提供一个C++的帮助文档:cplusplus,大部分时候都挺好用的,所有函数都有例程,还可以在线跑例程。

二进制模式与文本模式

在使用fopen_s打开文件时,可以在第三个参数_Mode中添加字符b来开启二进制模式,否则为文本模式。

例如,fopen_s(&oldFile, txtFilePath, "rb")就是开启了二进制模式。

这两者的区别几乎只在于换行符,在本人的编程环境 Win10 Visual Studio 2019 (v142) 下:

  • 二进制模式读取的换行符为2个字符\r\n;而文本模式为2个字符\n\n
  • 二进制模式写入\n再读取为\n;而文本模式写入\n再读取为\r\n,即文本模式将\n填补为了完整的换行符

可以这么理解:

  • 二进制模式下,写入、读取和实际存储的数据,一定相同
  • 文本模式下,写入、读取和实际存储的数据,不一定相同

fseek的坑

fseek的第三个参数_Origin有以下三个选择:

常量 代表的参考位置
SEEK_SET 文件开头
SEEK_CUR 文件指针的当前位置
SEEK_END 文件末尾

(第二个参数_Offset代表相对于参考位置的偏移量,在此不展开赘述)

有趣的事情来了,使用SEEK_SET或者SEEK_END结合适当的偏移量都可以让文件指针换行,但SEEK_CUR无论偏移多少都无法让文件指针换行,十分地不明所以。

源码

Talk is cheap. Show me the code.

#include <stdio.h>
#include <string.h>int main()
{//初始化变量FILE* oldFile;FILE* newFile;char txtFilePath[] = "data.txt";char tmpFilePath[] = "data_tmp.txt";//用"r"方式打开文件进行读取,"w"方式打开文件进行写入//使用二进制模式而不是文本模式打开文件(后面加了"b"),是为了处理起来更准确//二进制模式可以保证写入什么字符,就是什么字符,主要是在换行符上有作用//二进制模式下如果写入"\n",就是1个字符"\n",而文本模式下会自动填充成2个字符"\r\n"if (fopen_s(&oldFile, txtFilePath, "rb") || fopen_s(&newFile, tmpFilePath, "wb")) {printf("Error while opening file. \n");return 1;}char buffer = 0; //存储读取的字符//从文件末尾开始向前寻找"\n"换行符,并记录位置int curPos = 1; //当前光标位置while (true) {fseek(oldFile, -curPos, SEEK_END); //移动光标到文件倒数第curPos个字符前if (ftell(oldFile) == 0) {//若没有查找到,且光标已经位于文件开头,说明文件只有一行,则退出循环,删除该行break;}buffer = fgetc(oldFile); //读取字符到buffer//printf("%c", buffer); //输出查看if (buffer == '\n') {//注:C++中,双引号""表示字符串,单引号''表示字符,字符与字符串不能进行比较运算//换行符在二进制模式下为2个字符"\r\n",在文本模式下为2个字符"\n\n"//若查找到了,说明光标处于"\r"和"\n"之间,将光标再前移1次fseek(oldFile, -curPos - 1, SEEK_END); //将光标定位在倒数第二行的换行符前//退出循环,删除该换行符及之后的内容break;}else {//若没有查找到,则继续向前查找curPos++;}}int endPos = ftell(oldFile); //记录该光标位置//将从文件开头到endPos的内容复制到临时文件中fseek(oldFile, 0, SEEK_SET); //当前光标回到文件开头while (true) {curPos = ftell(oldFile);if (curPos == endPos) {break;}buffer = fgetc(oldFile); //读取字符到bufferfputc(buffer, newFile);}//关闭文件,保存fclose(oldFile);fclose(newFile);//删除旧文件,将临时文件名称改为旧文件名称,得到新文件remove(txtFilePath);if (rename(tmpFilePath, txtFilePath)) {printf("Error while renaming file. \n");return 2;}//结束printf("Successful. \n");return 0;
}

结语

很久没写C了,其实C++会的也不多……一直都是纯C写得多一点。

C给人的感觉就是一切都尽在掌握,自己会对代码的一举一动了如指掌,以及无比地僵硬(其实我还挺喜欢这种感觉的)。

网上的代码千奇百怪,还是要自己动手,才能写出简洁高效的代码!

C语言删除TXT文本文件最后一行相关推荐

  1. php删除txt文件最后一行

    /** * 删除文件最后一行 * @param $file_path 文件路径 */ public function delLastLine($file_path){ $file = $fp = fo ...

  2. 批量删除 txt 记事本文本文件中的某一行或一些行

    概要:我们有时候需要批量删除 txt 记事本文本文件中的某一行或者一些行,有没有一种快速的方式,能够让我们批量的删除记事本文本文件中的这些行呢?现在给大家介绍一种简单的方法,去批量的删除记事本文本文件 ...

  3. 从键盘输入一行字符,写入到string.txt文本文件中

    <程序设计基础实训指导教程-c语言> ISBN 978-7-03-032846-5 p197 8.1.2 上级实训内容 [实训内容1]从键盘输入一行字符,写入到string.txt文本文件 ...

  4. C语言:编写一个程序,建立一个abc.txt文本文件,向其中写入“this is a test”,然后显示该字符串

    /*编写一个程序,建立一个abc.txt文本文件,向其中写入"this is a test",然后显示该字符串*/ #include <stdio.h> #includ ...

  5. 如何用c语言从txt文件中读取数据

    用C语言从txt文件中读取数据,可以使用C标准库文件自带的文件接口函数进行操作. 一.打开文件: FILE *fopen(const char *filename, const char *mode) ...

  6. c语言读取一行的前几个字符串,c语言读取文件某一列 c语言 读取文件中某一行的前一行...

    各种格式的文件用什么软件打开.$$$TemporaryFile)Q7?5g4U5m&_.@.m;K"S.$$AOS/2club.looaoo.net-s;X'a)B.N,w7\;{9 ...

  7. vba打开txt文件_VBA基础入门(34)读取txt文本文件

    对于这样的txt文本文件,我们怎么一行一行去读取数据呢? #00001 65536 *00001 65536 说说常用的两种方法,一种是把txt文本文档读到Excel中,然后获取最大行数,做个循环来遍 ...

  8. xdf文件改word_真正Txt 文本文件和Doc Word文件批量互转工具

    电近经常上网下载小说文本,电脑里一大堆,虽然文本文件简洁方便,可是用记事本打开阅读,眼睛看起来却很累,还是觉得保存为WORD文件,阅读起来更舒服,也许一个两个TXT文本,转换成WORD,我们直接打开复 ...

  9. VB 读写TXT文本文件函数

    以下两个函数分别读取TXT文本文件与写入文件 Private Function GetTXT(Path As String) '读取文本     Open Path For Input As #1   ...

最新文章

  1. 走近webpack(0)--正文之前的故事
  2. java 序列化 例子_Java序列化和反序列化例子
  3. Java SpringMVC框架学习(二)httpServeltRequest和Model传值的区别
  4. linux安装库文件下载,Linux下的Curses库的下载与安装
  5. 用画小狗的方法来解释Java中的值传递
  6. Android性能优化 笔记
  7. 概率论与数理统计 (二)计算题和应用题
  8. 大数据将植物学研究带入新境界
  9. 氨基酸密码子表(Amino Acid Codon)
  10. idea 引入包报错:Unable to provision, see the following errors
  11. linux pv 文件夹,Linux 实用命令 - pv
  12. IDEA Android开发 连接华为手机调试
  13. java里short,int,long,float,double范围及可写位数
  14. python爬取酷狗音乐json数据为空_【Python3爬虫】下载酷狗音乐上的歌曲
  15. 微信公众号开发-----接送事件推送之关注/取消关注
  16. 阿里资深技术专家带你聊一聊——服务端的接口测试...
  17. Java面向对象综合训练综合练习
  18. 方舟生存进化服务器文件设置,方舟生存进化私人服务器设置教程[多图]
  19. 【亲测可访问】外网如何访问局域网本地搭建的服务器
  20. C++游戏服务器开发

热门文章

  1. 飞书开放平台-发送个人群名片消息示例
  2. 【转】Ninject的使用
  3. nacos注册中心发现不到服务
  4. 机器学习3-线性代数回顾
  5. CAN总线加终端电阻的原因
  6. 纯电动汽车结构分类和整体认识
  7. Android开发:使用Java对手机截图图片进行任意区域的颜色对比度处理操作
  8. 2023年湖北武汉安全员ABC报名条件和报名资料是什么?全国通用?
  9. $confirm的自定义使用
  10. 蛋糕店小程序怎么做,需要哪些功能