Search code examples
c++if-statementfstreamofstream

Opening an fstream for reading/ writing (binary)


A number of options are available to the user in this program: Option 1: record entry (terminated by EOF key). Option 2: displays records. Option 3: exit program.

The user may then repeat this process. I wish to avoid overwriting records by seeking to the end of the file, and ensure that the close() and open() calls are correct.

After declaring:

fstream fs("file", ios_base::in | ios_base::out | ios_base::binary);

is it necessary to explicitly call open;

fs.open("file", ios_base::in | ios_base::binary);

if it is necessary: must binary mode be specified? and is it necessary to clear the stream prior to writing successively?

struct record
{
    char firstname[MAX], lastname[MAX];
    int score;
};

int main(){

  record r;
  // must the modes be listed in a particular order?
  fstream fs("file", ios_base::in |ios_base::out | ios_base::binary);

  if(choice == 1) // option 1 for writing 
  {
    fs.clear(); // is it necessary to clear?
    // is it necessary to explicitly call open [and close] within 'if'
    fs.open("file", ios_base::in | ios_base::binary); 
    fs.seekp(0, ios_base::end); //attempt to avoid overwriting previous records 

    fs.write( (char *)&r, sizeof(r) );
    fs.close(); // is it best to close the file here...
  } 
  else if(choice == 2){ /*Display records*/ }
  else if(choice == 3){ exit(1); }

  /* would it be incorrect to fs.close() here and not call fs.open() */

  return 0;
}

Solution

  • After declaring:

    fstream fs("file", ios_base::in | ios_base::out | ios_base::binary);
    

    is it necessary to explicitly call open;

    fs.open("file", ios_base::in | ios_base::binary);
    

    File streams can be opened in their constructors or by calling the member function open(). If a file has already been opened prior to calling open() then this is an error reported by the stream's error. It is not necessary to call open() if the file is already been opened.

    Note that you can default-construct the file stream so you don't have to make the decision on how to open the stream on construction.

    std::fstream fs;
    

    This is a stream that has no associated file, so now you can call open() with correct semantics.

    must binary mode be specified?

    Yes, binary mode is never a default open mode. If you need a file to be in binary mode, then this is option needs to be specified.

    is it necessary to clear the stream prior to writing successively?

    The member function clear() is meant to clear the error mask, which can be written to because of a failed read/write/etc. Only if there are errors that you wish to clear then to do so is fine. But you probably don't need to do this since you just opened the file without any prior IO operation.

    would it be incorrect to fs.close() here and not call fs.open()

    You normally don't need to explicitly call close() unless you want to open a new file on the stream. Since std::fstream is an RAII class, close() will be called at the end of its scope (at the end of main).

    If you need to open a new file, then you should call close() first before calling open().


    Also, a suggestion: If you want a file to open at the end, then use the std::ios_base::ate openmode:

    if (choice == 1) {
        fs.open("file", ios_base::in | ios_base::binary | ios_base::ate);
        //                                                ^^^^^^^^^^^^^
        fs.write( (char *)&r, sizeof(r));
    }