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.