How to update data at a particular line in a file?

24.5k views Asked by At

Consider i have following file ("testt.txt")

abc
123
def
456
ghi
789
jkl
114

Now if i wanted to update the figure next to name ghi (i.e. 789), how would i do it?

The following code helps me reach there quickly no doubt, but how to update it quickly?

#include<iostream>
#include<fstream>
#include<string>

using namespace std;

int main() 
{
    int counter = 0;
    string my_string;
    int change = 000;
    ifstream file ( "testt.txt" );

    while(!file.eof())
    {
        counter = counter + 1;
        getline(file, my_string, '\n');
        if (my_string == "ghi") 
        {
            ofstream ofile ( "testt.txt" );
            for (int i = 0; i < counter + 1; i++)
            {
                //reached line required i.e. 789
                //how to process here?
            }
            ofile.close();
            break;
        }
    }
    cout << counter << endl;
    file.close();
    return 0;
}

Clearly the counter here is 5 corresponding to "ghi", so counter + 1 would point to value 789. How to change it to 000?

------------SOLVED-----------FINAL CODE------

 #include<iostream>
 #include<fstream>
 #include<string>
 #include <cstdio>

using namespace std;

int main() 
{
string x;
ifstream file ( "testt.txt" );
ofstream ofile ( "test2.txt" );
while (!file.eof())
{
    getline(file,x);
    if (x == "789")
    {
        ofile << "000" << endl;
    }
    else
        ofile << x << endl;
}
file.close();
ofile.close();
remove("testt.txt");
return 0;
}

Output ("test2.txt")

abc
123
def
456
ghi
000
jkl
114
2

There are 2 answers

15
Marcus Müller On

Doing that is not generally easy, because file systems don't store files line-wise, but instead as sequence of bytes. So if you replace a line with let's say 4 characters in it by a line with 5 characters, you will overwrite something in your next line. You'd have to read the file into memory, and then re-write everything from your changed line on.

That's a horrible approach, because it is incredibly slow, and if you can avoid it by not using a text file to store this kind of information, you should do that. I generally recommend using something like sqlite, for which libraries for all relevant languages exist, if you need to store data in things that feel like tables; for other kind of data, there's other approaches than relational databases, but that depends on what you want to actually store.

0
anatolyg On

If you open a file with ifstream for reading, and then with ofstream for writing, the ofstream will either not work or overwrite the file - I am not sure which option is right, but neither is what you want.

So use std::fstream to open a file for reading and writing:

fstream file ( "testt.txt" );

After arriving to the proper place, use the seekp method to enable writing to the stream after reading from it (it often works without seekp, but when it fails, the bug is very difficult to find), as required by the Standard:

if (my_string == "ghi") 
{
    file.seekp(file.tellg());
    ...
    break;
}

When modifying files, you have to replace the existing bytes with the new ones. It's important to write exactly 3 bytes, so the value 789 is overwritten properly. So you may want to check the range:

if (change < 0 || change > 999)
    abort(); // or recover from the error gracefully

And set the width of the output field before writing it:

file << setw(3) << change;

If your code switches from writing back to reading, use file.seekg(file.tellp()) to ensure it works properly.