赞
踩
希望能将给定txt文件的最后一行(无论是空行还是第一行)删掉,并直接保存,而不是另存为某个新的txt文件。
例1:
原文件:
1234567
abcdefg
处理后:
1234567
例2:
原文件:
Hello World!
处理后:
Hello World!
例3:
原文件:
This is an example.
处理后
大体思路如下:
注:本文只用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) 下:
\r\n
;而文本模式为2个字符\n\n
\n
再读取为\n
;而文本模式写入\n
再读取为\r\n
,即文本模式将\n
填补为了完整的换行符可以这么理解:
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); //读取字符到buffer fputc(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给人的感觉就是一切都尽在掌握,自己会对代码的一举一动了如指掌,以及无比地僵硬(其实我还挺喜欢这种感觉的)。
网上的代码千奇百怪,还是要自己动手,才能写出简洁高效的代码!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。