C++ – Replace line in txt file c++

cfstreamostream

I just wondering cause i have a text file containing STATUS:USERID:PASSWORD in accounts.txt

example it would look like this:

OPEN:bob:askmehere:

OPEN:john:askmethere:

LOCK:rob:robmypurse:

i have a user input in my main as such user can login 3x else status will change from OPEN to LOCK

example after 3 tries of john

before:

OPEN:bob:askmehere:

OPEN:john:askmethere:

LOCK:rob:robmypurse:

after:

OPEN:bob:askmehere:

LOCK:john:askmethere:

LOCK:rob:robmypurse:

what i have done is:

void lockUser(Accounts& in){
// Accounts class consist 3 attributes (string userid, string pass, status)

ofstream oFile;
fstream iFile;
string openFile="accounts.txt";
string status, userid, garbage;
Accounts toupdate;

oFile.open(openFile);
iFile.open(openFile);

    while(!iFile.eof()){

        getline(iFile, status, ':');
        getline(iFile, userid, ':');
        getline(iFile, garbage, '\n');


        if(userid == in.getUserId()){

            toupdate.setUserId(in.getuserId());
            toupdate.setPassword(in.getPassword());
            toupdate.setStatus("LOCK");
            break;
    }

    //here i should update the account.txt how do i do that?
    ofile.open(openFile);

    ofile<<toupdate.getStatus()<<":"<<toupdate.getUserId()":"<<toupdate.getPassword()<<":"<<endl;
}

Best Answer

There are two common ways to replace or otherwise modify a file. The first and the "classic" way is to read the file, line by line, check for the line(s) that needs to be modified, and write to a temporary file. When you reach the end of the input file you close it, and rename the temporary file as the input file.

The other common way is when the file is relatively small, or you have a lot of memory, is to read it all into memory, do the modification needed, and then write out the contents of the memory to the file. How to store it in memory can be different, like a vector containing lines from the file, or a vector (or other buffer) containing all characters from the file without separation.

Your implementation is flawed because you open the output file (which is the same as the input file) inside the loop. The first problem with this is that the operating system may not allow you to open a file for writing if you already have it open for reading, and as you don't check for failure from opening the files you will not know about this. Another problem is if the operating system allows it, then your call to open will truncate the existing file, causing you to loose all but the very first line.


Simple pseudo-ish code to explain

std::ifstream input_file("your_file");
std::vector<std::string> lines;
std::string input;
while (std::getline(input_file, input))
    lines.push_back(input);

for (auto& line : lines)
{
    if (line_needs_to_be_modified(line))
        modify_line_as_needed(line);
}

input_file.close();

std::ofstream output_file("your_file");
for (auto const& line : lines)
    output_file << line << '\n';