【问题标题】:Finding and replacing string tokens in a file in C++ using win32 API使用 win32 API 在 C++ 文件中查找和替换字符串标记
【发布时间】:2009-03-04 12:04:41
【问题描述】:

我正在尝试找到一种方法,用另一个字符串替换文件中字符串标记的所有实例。

如何在 C++ 中使用 win32 API 执行此操作?

在其他语言中,这很容易做到,但在 C++ 中,我只是迷路了。

编辑:在某些情况下,这是针对 WiX 自定义操作。所以可移植性不是主要优先事项,只是最简单的解决方案。

【问题讨论】:

  • 您在评论中说“这是针对 msi 自定义操作。外部库是不行的。”。你能在你的问题中详细说明这个想法/限制吗?

标签: c++ winapi string


【解决方案1】:

如果文件适合内存——那就更简单了。调用 OpenFile() 打开文件,调用 GetFileSize() 确定文件大小,分配足够的内存,调用 ReadFile() 读取文件,然后调用 CloseFile。在内存中进行替换(使用 strstr() 或类似函数),然后再次使用 OpenFile()、WriteFile()、CloseFile()。

如果文件很大 - 创建一个临时文件并分块读取源文件并将过滤后的文本写入临时文件,然后调用 DeleteFile() 删除原始文件并调用 MoveFile() 移动过滤后的文件。

【讨论】:

    【解决方案2】:

    您可以使用Boost.Regex 库,它应该类似于您在其他平台上找到的大部分功能。

    它会像这样工作:

    example 中,您将了解如何替换匹配模式的字符串。

    #include <boost/regex.hpp>
    #include <string>
    
    int main()
    {
        boost::regex pattern ("b.lug",boost::regex_constants::icase|boost::regex_constants::perl);
        std::string stringa ("Searching for bolug");
        std::string replace ("BgLug");
        std::string newString;
    
        newString = boost::regex_replace (stringa, pattern, replace);
    
        printf("The new string is: |%s|\n",newString.c_str());
    
        return 0;
    }
    

    但您当然必须添加文件读取/写入。

    【讨论】:

    • 这是一个 msi 自定义操作。外部库是不行的。
    • 在这种情况下,它会变得有点复杂。也许您可以使用 C++ 流并创建一个将某些字符串替换为其他字符串的操纵器。见stackoverflow.com/questions/535444/…
    • “外部库”是指 DLL 吗?因为 Boost 可以静态链接到您的可执行文件。实际上,如果您使用 xpressive 而不是正则表达式,它是一个仅包含标头的库。根本没有联系。
    【解决方案3】:

    根据Sharptooth 的解决方案,我敲了一些C 代码来查找和替换文件。我使用 stdio 调用(strlen、strstr、strcpy 和 strcat)来进行字符串操作(而不是 win32 调用),所以你唯一的依赖是 C 运行时间。

    这当然不是我会在生产系统中使用的代码。我会使用工具包字符串操作库中的东西来使这个更干净(而不是使用固定长度的缓冲区)。我可能不会使用 boost,我不喜欢开销。但我想您可能会喜欢一个仅包含基础知识的示例(注意,这会将更改后的缓冲区写入 .temp)。

    #include <stdio.h>
    
    #define BUF_LEN 2048
    
    int findAndReplace (const char * file, const char * find, const char * replace)
    {
        int replaceCount = 0;
        FILE * f = fopen (file, "rt");
    
        if (strstr(replace, find))
            return 0; // replacing blah with stuff_blah_stuff
    
        unsigned int findLen = strlen (find);
        char tempFile [BUF_LEN];
        strcpy (tempFile, file);
        strcat (tempFile, ".temp");
        FILE * writeF = fopen (tempFile, "wt");
    
        if (!f || !writeF)
            return 0;
    
        printf ("Processing %s - %s to %s\n", file, find, replace);
    
        char lineBuf [BUF_LEN];
        memset (lineBuf, 0, BUF_LEN);
        char tempLineBuf [BUF_LEN];
        memset (tempLineBuf, 0, BUF_LEN);
    
        // read each line of the file
        while (fgets (lineBuf, BUF_LEN, f))
        {
            // get the position of find in the line buffer
            char * pos = strstr (lineBuf, find);
            while (pos)
            {
                strncpy (tempLineBuf, lineBuf, pos - lineBuf);
                strcat (tempLineBuf, replace);
                strcat (tempLineBuf, pos + findLen);
                replaceCount++;
    
                // replace the current buf with the replaced buffer
                strncpy (lineBuf, tempLineBuf, BUF_LEN);
                memset (tempLineBuf, 0, BUF_LEN);
    
                pos = strstr (lineBuf, find);
            }
    
            printf ("writing new line %s\n", lineBuf);
            fputs (lineBuf, writeF);
        }
    
        fclose (f);
        fclose (writeF);
    
        return replaceCount;
    }
    
    int main ()
    {
        printf ("Made %d replacements\n", findAndReplace ("blah.txt", "marker", "testing_blah"));
    }
    

    【讨论】:

      【解决方案4】:

      为什么必须使用 Win32 API?使用直接 C++ 很容易,我不会通过添加人为约束来混淆这个问题。只需打开您的输入文件,打开一个输出文件,然后从您的输入中读取一行。虽然您没有在输入文件中点击 EOF,但请使用正则表达式来查找您的令牌。如果找到它,请将其替换为您的文本。将该行写入输出文件。从输入中读取另一行。当您在输入上获得 EOF 时,将其关闭。确保任何挂起的输出都从输出缓冲区中刷新。关闭输出文件。完成。

      【讨论】:

        猜你喜欢
        • 2020-08-12
        • 2011-05-25
        • 1970-01-01
        • 2013-02-19
        • 2015-04-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-03
        相关资源
        最近更新 更多