Delete and replace a Specific Line in .txt file

Viewed 798

I'm struggling with my C++ project related to file handling and need one help.

Here is my movies.txt file

SNO, Name, NoOfPeopleLiked
1, The Shawshank Redemption, 77 
2, The Godfather, 20        
3, Into The Wild, 35
4, The Dark Knight, 55      
5, 12 Angry Men, 44     
6, Schindler's List, 33
7, The Lord of the Rings: The Return of the King, 25
8, Pulp Fiction, 23
9, The Good, the Bad and the Ugly, 32   
10, The Lord of the Rings: The Fellowship of the Ring, 56

I want to delete the specific line by just inputting the movie name of that line. For Example when I input movie name "12 Angry Men" The whole line no 5 should be deleted and replaced with the updated line having incremented NoOfPeopleLiked values from 5, 12 Angry Men, 44 to 5, 12 Angry Men, 45. How can I delete that specific line and update the liked value whenever I input movie name?


But When I input the movie name all lines get deleted till line no 6 and the output file looked like this.


    , Schindler's List, 33
7, The Lord of the Rings: The Return of the King, 25
8, Pulp Fiction, 23
9, The Good, the Bad and the Ugly, 32   
10, The Lord of the Rings: The Fellowship of the Ring, 56

Kindly help me to resolve this issue? Here is my code:

void search()
{
    ifstream file;
    file.open("movies.txt");
    cout << "Enter the name of Movie : " << ' ';
    getline(cin, search_movie);
    if (file.is_open())
    {
        while (getline(file, line, ','))
        {
            if ((line.find(search_movie, 0)) != string::npos)
            {
                file >> liked;
                file >> serial;
                cout << serial << " The movie '" << search_movie << "' has been found in database and " << liked << " people like this movie" << endl;
                cout << "Do you like it as well (y/n)" << ' ';
                char z;
                cin >> z;
                if (z == 'y' || z == 'Y')
                {
                    update(search_movie, file);
                }
            }
        }
    }
    else
    {
        cout << "your file could not be opened" << endl;
    }
    file.close();
}

    void update(string search_movie, ifstream& file1)
    {
        ofstream temp;
        string linee;
        temp.open("temp.txt", ios::out);
        while (getline(file1, linee))
        {
            cout << linee << endl;
            if (line.substr(0, search_movie.size()) != search_movie)
            {
                temp << linee << endl;
            }
        }
        file1.close();
        temp.close();
        remove("movies.txt");
        rename("temp.txt", "movies.txt");
    }
};
1 Answers

Here is a working example of what you want to do: it increments the number of likes for a movie. It does not store the contents of the whole file into the buffer. The file might be of a large size, so it might not be very efficient.

#include <fstream>
#include <iostream>
#include <string>
 
int main()
{
    std::fstream fileMovies{"sample.txt",
                            std::ios_base::in | std::ios_base::out | std::ios_base::binary};
    if (!fileMovies.is_open())
    {
        std::cerr << "Failed to open file" << std::endl;
        return -1;
    }

    std::string movieName{};
    std::getline(std::cin, movieName);

    std::string line{};
    line.reserve(256);

    long long int pos = fileMovies.tellp();
    for (line; std::getline(fileMovies, line);)
    {
        if (line.find(movieName) != std::string::npos)
            break;
        line.clear();
        pos = fileMovies.tellp();
    }

    if (fileMovies.eof())
    {
        std::cerr << "Failed to find the movie by name" << std::endl;
        return -1;
    }

    long long int curPos = fileMovies.tellp();

    // TODO: check format
    long long int commaPos = line.rfind(',');
    fileMovies.seekp(pos + commaPos + 2);

    int liked = 0;
    fileMovies >> liked;
    fileMovies.seekp(pos + commaPos + 2);
    fileMovies << ++liked;

    return 0;
}

Output:

PS C:\dev\builds\editfile\Release-Visual Studio\bin> cat .\sample.txt
SNO, Name, NoOfPeopleLiked
1, The Shawshank Redemption, 77
2, The Godfather, 20
3, Into The Wild, 35
4, The Dark Knight, 55
5, 12 Angry Men, 44
6, Schindler's List, 33
7, The Lord of the Rings: The Return of the King, 25
8, Pulp Fiction, 23
9, The Good, the Bad and the Ugly, 32
10, The Lord of the Rings: The Fellowship of the Ring, 56
PS C:\dev\builds\editfile\Release-Visual Studio\bin> .\main.exe
Angry
PS C:\dev\builds\editfile\Release-Visual Studio\bin> cat .\sample.txt
SNO, Name, NoOfPeopleLiked
1, The Shawshank Redemption, 77
2, The Godfather, 20
3, Into The Wild, 35
4, The Dark Knight, 55
5, 12 Angry Men, 45
6, Schindler's List, 33
7, The Lord of the Rings: The Return of the King, 25
8, Pulp Fiction, 23
9, The Good, the Bad and the Ugly, 32
10, The Lord of the Rings: The Fellowship of the Ring, 56

Keep in mind, that you can't append new characters in the middle of the file (nor can you erase them). You can only overwrite the existing ones at the current position. So in order for this to work properly, you should use the number of likes with trailing spaces, or in format like 0045. Also, pay attention that you have to use std::fstream with flags in | out | binary. Binary is necessary in order to properly count the current position.

Related