C++ - Find and replace in text file (standard system libraries)

c++, file, replace, text

Solution

Here is a possible solution that uses:

- `std::getline()`

- `std::copy()`

- `istream_iterator`

- `ostream_iterator`

- `vector`

Example:

#include <iostream>
#include <fstream>
#include <iterator>
#include <algorithm>
#include <string>
#include <vector>

struct modified_line
{
    std::string value;
    operator std::string() const { return value; }
};
std::istream& operator>>(std::istream& a_in, modified_line& a_line)
{
    std::string local_line;
    if (std::getline(a_in, local_line))
    {
        // Modify 'local_line' if necessary
        // and then assign to argument.
        //
        a_line.value = local_line;
    }
    return a_in;
}

int main() 
{
    std::ifstream in("file.txt");

    if (in.is_open())
    {
        // Load into a vector, modifying as they are read.
        //
        std::vector<std::string> modified_lines;
        std::copy(std::istream_iterator<modified_line>(in),
                  std::istream_iterator<modified_line>(),
                  std::back_inserter(modified_lines));
        in.close();

        // Overwrite.
        std::ofstream out("file.txt");
        if (out.is_open())
        {
            std::copy(modified_lines.begin(),
                      modified_lines.end(),
                      std::ostream_iterator<std::string>(out, "\n"));
        }
    }

    return 0;
}

I am not sure exactly what the manipulation of the lines should be but you could use:

- `std::string::find()` and `std::string::substr()`

- `boost::split()`

EDIT:

To avoid storing every line in memory at once the initial `copy()` can changed to write to an alternative file, followed by a file `rename()`:

std::ifstream in("file.txt");
std::ofstream out("file.txt.tmp");

if (in.is_open() && out.open())
{
    std::copy(std::istream_iterator<modified_line>(in),
              std::istream_iterator<modified_line>(),
              std::ostream_iterator<std::string>(out, "\n"));

    // close for rename.
    in.close();
    out.close();

    // #include <cstdio>
    if (0 != std::rename("file.txt.tmp", "file.txt"))
    {
        // Handle failure.
    }
}

Problem

I am looking for some advice. My situation: Application works with text local file. In file are somewhere tags like this: ``` correct = "TEXT" ``` . Unfortunatelly, there can be unlimited spaces between correct, = and "TEXT". Obtained text is testing in function and may be replaced (the change must be stored in the file). ``` correct = "CORRECT_TEXT" ``` My current theoretical approach: With ofstream -- read by line to string. Find tag and make change in string. Save strings as lines to the file. Is there some simplify way (with iterators?) in C++ with using standard system libraries only (unix). Thank you for your ideas.

Original source