为了不忘记C(在工作中我主要处理XSLT和其他语言不那么有趣),我不时会写一个小实用程序。
一个应用程序替换任何类型文件中的字符串而不生成第二个文件(是否有一个更好的短语来描述这个?)是我今天想到的。
我想出的是:
#include <stdio.h>
#include <string.h>
#define CHUNKLEN 256
void replcnks(char *str, char *cnk1, char *cnk2);
int main(int argc, char **argv)
{
FILE *file;
char *old, *new, *fname, buf[CHUNKLEN];
long len;
if(argc != 4)
{
puts("Invalid arguments\n");
return 0;
}
old = argv[1];
new = argv[2];
fname = argv[3];
file = fopen(fname, "rb+");
do
{
len = fread(buf, 1, CHUNKLEN, file);
replcnks(buf, old, new);
fseek(file, -len, SEEK_CUR);
fwrite(buf, 1, len, file);
fseek(file, len, SEEK_CUR);
}
while(len == CHUNKLEN);
fclose(file);
return 0;
}
void replcnks(char *str, char *cnk1, char *cnk2)
{
char *pos;
int clen1 = strlen(cnk1), clen2 = strlen(cnk2);
while((pos = strstr(str, cnk1)))
{
memmove(pos + clen2, pos + clen1, strlen(pos) - clen1 + 1);
memcpy(pos, cnk2, clen2);
}
}
该程序有效,但当替换字符串的大小与原始字符串不同时,会产生轻微错误。当它更长时,文件的结尾被剪切;当它更短时,输出在某些地方有一些垃圾值。我想问题出在fseek
s。
如何修复此计划?
解决方案可能很简单,但我想我今天没有脑力 - 但我想和平地睡觉:)。
答案 0 :(得分:4)
你无法真正做到你想要做的事情,因为用一个不同大小的块替换一个文件块是没有好办法的。
如果被替换的字符串跨越块边界,它也会失败。
如果用较长的字符串替换短字符串,它可能会做很糟糕的事情,因为缓冲区中没有空间。
如果你真的想要这样做,你必须有一些缓冲方案,你可以单独跟踪读写,这样你就不会写你还没读过的字节。然后你仍然需要应对增长或截断文件......
答案 1 :(得分:1)
JasonD说的是 - 你试图用一个不同大小的文件来覆盖一些文件,文件系统无法神奇地缩小/扩展文件的中间以适应。我将源加载到RAM中,然后创建一个新文件,或者删除/重命名/备份源,然后用原始名称写出结果。