0

为了不忘记 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);
    }
}

该程序可以运行,但是当替换字符串的大小与原始字符串的大小不同时,它会产生小错误。当它较长时,文件的结尾被剪切;当它更短时,输出在某些地方会有一些垃圾值。我猜问题出在其中一个fseeks。

如何修复这个程序?

解决方案可能很简单,但我想我今天脑力不够——但我想睡个安稳觉:)。

4

2 回答 2

4

你不能真正做你想做的事,因为没有好的方法可以用不同大小的块替换文件的块。

如果被替换的字符串落在块边界上,它也会失败。

如果用更长的字符串替换短字符串,它可能会做非常糟糕的事情,因为缓冲区中没有空间。

如果您真的想这样做,则必须有某种缓冲方案,在其中分别跟踪读取和写入,这样您就不会写入尚未读取的字节。然后你仍然必须应对文件的增长或截断......

于 2012-12-17T17:57:44.580 回答
1

JasonD 所说的 - 你试图用不同大小的文件覆盖一个文件,文件系统无法神奇地缩小/扩展文件的中间以适应。我会将源加载到 RAM 中,然后创建一个新文件,或者删除/重命名/备份源,然后使用原始名称写入结果。

于 2012-12-17T18:05:02.860 回答