0

/* I want to transfer the content from the first file ("constituencies") to the second ("temp") and then delete the original ("constituencies") file then rename() ("temp") to ("constituencies") so it can be refreshed with a specific entry/line be deleted from the file by first finding it and then not adding it in the newly generated file ("temp") and then deleting the old ("constituencies") file and renaming ("temp") as the new ("constituencies") but both of my files get deleted in the process, please help */

void updateOrDelete()
{
        fstream constituencies("constituencies.txt", ios::out | ios::in);
        fstream temp("temp.txt", ios::out | ios::in);
        string deleteline;
        string line;


        cout << "Which constituency do you want to remove? \n";
        cin >> deleteline;

        while (getline(constituencies, line))
        {
                if (line != deleteline)
                {
                        temp << line << endl;
                }
        }

    constituencies.close();
    temp.close();

        remove("constituencies.txt");
        rename("temp.txt", "constituencies.txt");
}
  • In your previous code you had `constituencies.txt` open in a global file object. Depending on your OS you may not be able to delete an open file. – drescherjm Jun 02 '20 at 20:23
  • Don't open files for both reading and writing unless you really intend to do both. Use `ifstream` and `ofstream`. – molbdnilo Jun 02 '20 at 20:47
  • @drescherjm, you're right I did that and it wasn't working in global before, thanks much for the previous answer and the explanation to this one as well – Danyal Ali Jun 02 '20 at 21:20

1 Answers1

1

This line fails if temp.txt does not exist:

fstream temp("temp.txt", ios::out | ios::in);

but you don't notice that since you don't check if it was successful.

Remedy:

ifstream constituencies("constituencies.txt");
if(constituencies) {
    // constituencies.txt successfully opened for reading
    ofstream temp("temp.txt");
    if(temp) {
        // temp.txt successfully opened for writing
    } else {
        // fail
    }
} else {
    // fail
}

Here's a full version of the function with some added error checking and the user interaction moved out so you'll have to call it with the deleteline you want to remove from the file.

// returns true if successful and false otherwise
bool updateOrDelete(const std::string& deleteline) {
    static const char* orig = "constituencies.txt";
    static const char* temp1 = "temp1.txt";
    static const char* temp2 = "temp2.txt";

    // make sure you are the only one processing the file
    if(std::rename(orig, temp1) == 0) {
        // open for reading and check if it succeeded
        if(std::ifstream in(temp1); in) {
            // open for writing and check if it succeeded
            if(std::ofstream out(temp2); out) {
                std::string line;
                // do your processing
                while(std::getline(in, line)) {
                    if(line != deleteline) {
                        out << line << '\n';
                    }
                }
                // check if the new file is still in a good state before closing it
                bool success = static_cast<bool>(out);
                out.close();
                in.close();
                if(success) {
                    // all's well - move the processed file into place
                    // and remove the old (renamed) original
                    return std::rename(temp2, orig) == 0 && std::remove(temp1) == 0;
                }
                // processing failed
                // remove the corrupt/truncated file
                std::remove(temp2);
            }
        }
        // try to restore the original file
        std::rename(temp1, orig);
    }
    // if we get here, something failed
    return false;
}
Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
  • You're right I forgot to declare ofstream temp for writing into it and now it's working but, My constituencies file also inputs data so I have to declare it fstream and my temp file will be renamed constituencies at the end of the function, hence it's attributes will follow so I also have to declare it fstream as well, right ? Also even if a file is fstream I still will have to declare it's ofstream when writing into it, correct ? Please answer both questions for my clarity, Otherwise the problem has been solved, Thank you very much. – Danyal Ali Jun 02 '20 at 21:15
  • The mode you use when processing the file (`in` or `out` or both) has nothing to do with the file's filesystem attributes. You can open a file for reading at one point and for writing at another. If you use `fstream`, `ifstream` or `ofstream` doesn't matter either when it comes to the file's attributes. Does that clear things up? – Ted Lyngmo Jun 02 '20 at 21:17