-1

I'm trying to access a .txt file in read&write mode and then overwrite a specific portion of the text.

The .txt file stores a list of users, each one identified as such:

 UserType:FirstName:LastName:Email:Password:endl:

The method in charge of making changes is tasked to parse the file and modify the email camp.

It takes in input an User object and the new email that has to be registered.

void userContainer::modifyEmail(User & u, string newmail){
    fstream user_file;
    string temp;
    user_file.open("users.txt");
    while(!(user_file.eof())){
        getline(user_file,temp,':');

        if(temp==u.getEmail()){
            //save position of the email string
            long pos=user_file.tellg();
            //copy user data following the email
            string remaining_data;
            getline(user_file,remaining_data,'\n');
            //overwrite with newmail
            user_file.seekp(pos-(temp.size()+1));//positioning the pos value at the beginning of the email camp
            user_file.write(&newmail[0],newmail.size()); //overwriting with the new mail
            //writing remaining data;
            user_file.write(&remaining_data[0], remaining_data.size()); 
        }
    }
    user_file.close();
}

Upon running the method, no change whatsoever is applied to the users.txt file. The string "remaining_data" does, however, correctly register the strings following the email camp.

Deleting the portion of code which uses the remaining_data string does modify the file but, obviously, not in the way I want:

void userContainer::modifyEmail(User & u, string newmail){
    fstream user_file;
    string temp;
    user_file.open("users.txt");
    while(!(user_file.eof())){
        getline(user_file,temp,':');
        if(temp==u.getEmail()){
            //save position of the email string
            long pos=user_file.tellg();
            //overwrite with newmail
            user_file.seekp(pos-(temp.size()+1));
            user_file.write(&newmail[0],newmail.size());
        }
    }
    user_file.close();
}

Example:

Before modifyEmail is called:

admin:Cristiano:Ronaldo:cr7@fluffymail.com:cri7madr1d:endl:

After calling modifyEmail (without using remaining_data)

admin:Cristiano:Ronaldo:banana100000@hotmail.itmadr1d:endl:

Required behavior after calling the method

admin:Cristiano:Ronaldo:banana100000@hotmail:cri7madr1d:endl:
someCoder
  • 185
  • 3
  • 15

1 Answers1

0

Rather than trying to update the file in-place, it is much easier to write out a new file and then rename it at the end (after deleting the old one).

I'll leave it there, I'm sure you can manage if you heed the comments above.

Paul Sanders
  • 24,133
  • 4
  • 26
  • 48
  • I know this is a common solution for this kind of issue, but I really wanted to manage to accomplish this without creating a new file since it's a small project I'm working on in order to improve my skills with C++ – someCoder Dec 25 '18 at 19:08
  • Personally, I like to do things the easy way. You learn more, in the end. – Paul Sanders Dec 25 '18 at 19:57
  • I wouldn't worry about that unless the file is very large, and even then there will only be a significant difference if you are updating an entry near the end. This approach also has the advantage that it doesn't mangle the input file if it fails to complete for some reason, and if you have more than one update then you can easily 'batch' them. – Paul Sanders Dec 25 '18 at 20:20