用C语言来操作文件内容还是有点烦的(尤其是删除内容,或者是修改非等长度的内容),没有现成的API调用,只能自己手动写;
网上查了下资料基本就两个方案:
1、增加个临时文件;把源文件内容逐个字节或者逐行读取出来,然后修改或者丢弃,放到临时文件中,当把源文件中所有内容过滤后,再把临时文件全部覆盖回源文件;
2、读取到内存中修改;把整个文件读取到内存中,然后修改,再覆盖回到源文件;
第1种方案,会多一个临时文件,这样不太安全,使用C语言来做这种事,很大一方面就是考虑到安全性;
第2种方案,读取到内存中,这种方法有个缺陷是你不知道源文件大小,如果源文件很大的话,你要分配很大内存;
我们应该怀疑下,为什么 shell 命令可以很方便的删除、修改文件内容,这绝对不会有临时文件产生,也不会占用多大内存,或者可以说占用的内存不会随着文件的大小而改变?
我想了下,有个新方案,或许就是shell命令的原理;(我没有去研究shell命令的删除实现);
新方案是利用文件指针,如下图:
其实看下上面的图就应该知道了,就是利用文件指针,类似队列那样,一个是入队列一个是出队列;
流程:
a、首先保存两个位置,1、读取文件内容的偏移量;2、写入文件内容的偏移量;
b、用 seek + 读文件偏移量 来设置下读取内容指针偏移量,读取一行数据; 同时修改下读取偏移量;
c、对这一行数据进行判断,修改,或者删除;
d、用seek + 写入偏移量 来设置下文件位置指针,把 c 步骤中修改的内容回写到文件;同时修改下写入偏移量;
e、循环读取所有源文件内容;
f、根据写入文件偏移量(因为写入的才是有效的数据,写入偏移量就代表了文件大小),截取下文件,把无效内容干掉;
转载地址:http://blog.csdn.net/yuzhihui_no1/article/details/70188384
下面是代码实现:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <unistd.h>
#define BUFF_LEN 256
/*
* 删除文件中无效内容
* */
int clean_invalue_info(FILE *file_fd)
{
assert(file_fd);
char buff[BUFF_LEN] = {0};
int buff_len = 0;
long offset_read = 0;
long offset_write = 0;
while(fgets(buff, BUFF_LEN, file_fd)) {
buff_len = strlen(buff);
if (strstr(buff, "yzh")) { //有效数据要考虑移动
if (offset_read == offset_write) {
offset_write = offset_write + buff_len;
offset_read = offset_read + buff_len;
continue;
} else {
/*移动数据*/
fseek(file_fd, offset_write, SEEK_SET);
fputs(buff, file_fd);
offset_write = offset_write + buff_len;
offset_read = offset_read + buff_len;
fseek(file_fd, offset_read, SEEK_SET);
continue;
}
}
offset_read = offset_read + buff_len;
}
ftruncate(fileno(file_fd),offset_write);
}
int testt(FILE *file_fd)
{
char buff[BUFF_LEN] = {0};
int buff_len = 0;
long offset_read = 0;
char *str = "11111111111";
fseek(file_fd, 0, SEEK_SET);
fputs(str, file_fd);
fgets(buff, BUFF_LEN, file_fd);
printf("1. %s\n", buff);
buff_len = strlen(buff);
fgets(buff, BUFF_LEN, file_fd);
printf("2. %s\n", buff);
fseek(file_fd, buff_len, SEEK_SET);
fgets(buff, BUFF_LEN, file_fd);
printf("3. %s\n", buff);
return 0;
}
int main(int argc, char *argv[])
{
FILE *file_fd = fopen("./tt", "r+");
clean_invalue_info(file_fd);
// testt(file_fd);
fclose(file_fd);
return 0;
}
上面代码已经调试通过,为方便理解,没有优化过;
转载地址:http://blog.csdn.net/yuzhihui_no1/article/details/70188384