Поиск и замена строковых токенов в файле на C ++ с использованием Win32 API - PullRequest
2 голосов
/ 04 марта 2009

Я пытаюсь найти способ заменить все экземпляры строкового токена в файле другой строкой.

Как я могу сделать это в C ++ с Win32 API?

На других языках это легко сделать, но в C ++ я просто потерялся.

РЕДАКТИРОВАТЬ: Для некоторого контекста, это для пользовательского действия WiX. Таким образом, мобильность - это не главный приоритет, а самое простое решение.

Ответы [ 4 ]

5 голосов
/ 04 марта 2009

Если файл помещается в память - это проще. Вызовите OpenFile (), чтобы открыть файл, GetFileSize (), чтобы определить размер файла, выделите достаточно памяти, вызовите ReadFile (), чтобы прочитать файл, затем CloseFile. Сделайте замену в памяти (используйте strstr () или аналогичную функцию), затем снова OpenFile (), WriteFile (), CloseFile ().

Если файл большой - создайте временный файл и прочитайте исходный файл кусками и запишите отфильтрованный текст во временный файл, затем вызовите DeleteFile (), чтобы удалить оригинальный файл, и MoveFile (), чтобы переместить отфильтрованный файл.

3 голосов
/ 04 марта 2009

Вы можете использовать библиотеку Boost.Regex , которая должна напоминать большинство функций, которые вы найдете на других платформах.

Это будет работать так:

В этом примере вы найдете, как заменить строку, соответствующую шаблону.

#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;
}

но вы, конечно, должны добавить файл для чтения / записи.

2 голосов
/ 04 марта 2009

В соответствии с решением Sharp, я собрал код C, чтобы найти и заменить файл. Я использовал вызовы stdio (strlen, strstr, strcpy и strcat) для манипулирования строками (а не для вызовов win32), поэтому ваша единственная зависимость - это время выполнения C.

Это, конечно, не тот код, который я бы использовал в производственной системе. Я бы использовал материал из библиотек инструментов для работы со строками инструментария, чтобы сделать это намного чище (и не так сильно с буферами фиксированной длины). Я, вероятно, не использовал бы повышение, мне не нравятся накладные расходы. Но я подумал, что вам может понравиться пример только с основами (N.B. Это записывает измененные буферы в .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"));
}
1 голос
/ 04 марта 2009

Почему вы должны использовать Win32 API? Достаточно просто использовать прямой C ++, я бы не стал путать проблему, добавив искусственные ограничения. Просто откройте ваш входной файл, откройте выходной файл и прочитайте строку из вашего ввода. Пока вы не нажали EOF во входном файле, используйте регулярное выражение для поиска вашего токена. Если вы найдете его, замените его своим текстом. Запишите строку в выходной файл. Прочитайте еще одну строку из ввода. Когда вы получите EOF на входе, закройте его. Убедитесь, что любой ожидающий вывод сброшен из буфера вывода. Закройте выходной файл. Готово.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...