Thomas
Thomas

Reputation: 2959

fstream in and out on nonexistent file

Is it possible to open an fstream on a file that does not exist with both ios::in & ios::out without getting an error?

Upvotes: 12

Views: 18891

Answers (5)

Kai Petzke
Kai Petzke

Reputation: 2984

The answer to your question unfortunately is: "No", this is not possible in a single C++ statement.

Yes, many people will answer, that you can use the combined flags fstream::in | fstream::out | fstream::trunc. But that answer is nonsense. fstream::trunc means, that the output file will be truncated to size zero upon opening. But then, why would you like to open an empty file for reading and writing? Except for the rare case, that you need a file as a temporary store for some of your application's data, that you will first write and later read back, there is no use for this flag combination.

Some people recommend to first try to open with fstream::in | fstream::out (and possible further flags like fstream:app or fstream::binary as needed) and then check the file's error status: If the file could not be opened, then re-try the open operation including | fstream::trunc. This solution has several caveats, however. For example, if your file system is mounted via NFS, the first attempt to open the file in read/write-mode might fail due to temporary network issues. If the second attempt (the one including the fstream::trunc flag) then succeeds, there goes your wounderful data, that you have collected so far.

The safe solution is to first open the file for appending only (which will create the file, if it doesn't exist, but will not truncate it) and then close it immediately and open it a second time in read-write mode. This can be achieved with the following code: Note, that an ofstream is first constructed and then immediately discarded.

std::string filename { "test.txt" };
(void) std::ofstream(filename, std::ostream::app);
std::fstream file(filename);

Alternatively, if you need further flags, like binary, use:

std::string filename { "test.txt" };
(void) std::ofstream(filename, std::ofstream::app | std::fstream::binary);
std::fstream file(filename, std::fstream::in | std::fstream::out | std::fstream::binary);

I hope, that in C++25 (or whichever standard is next), they finally add a flag std::fstream::create to create non-existant output files, if read-write-mode is requested.

Upvotes: 6

johnsyweb
johnsyweb

Reputation: 141928

To open an fstream on a file that does not exist for input and output (random access) without getting an error, you should provide the flags fstream::in | fstream::out | fstream::trunc in the open (or constructor) call. Since the file does not already exist, truncating the file at zero bytes is no drama.

You may want an error when opening a file that doesn't exist when specifying only ios::in since you'll never be able to read from the stream so failing early in this case will prevent surprise failures later on.

Upvotes: 11

Mooing Duck
Mooing Duck

Reputation: 66961

std::fstream f("test.txt", std::ios_base::out);
f.close(); //file now exists always
f.open("test.txt", fstream::in | std::ios_base::out);
//f is open for read and write without error

I haven't checked to guarantee that it will open without error, but I feel pretty confident that it should.

Upvotes: 0

Draco Ater
Draco Ater

Reputation: 21226

#include <iostream>
#include <fstream>
using namespace std;

int main () {
  fstream f("test.txt", fstream::in | fstream::out);
  cout << f.fail() << endl;
  f << "hello" << endl;
  f.close();    
  return 0;
}

This code will print 1 and will not create "test.txt" file, if it does not exit. So it is not possible to open and fstream on a file that does not exist without getting an error.

Upvotes: 0

Secko
Secko

Reputation: 7716

#include <fstream> 

ofstream out("test", ios::out);
if(!out)
{
    cout << "Error opening file.\n";
    return 1;
}

ifstream in("test", ios::in);
if(!in)
{
    cout << "Error opening file.\n";
    return 1;
}

If an error occurs the message is displayed and one (1) is returned. However it is possible to compile and execute just ofstream out("test", ios::out); and ifstream in("test", ios::in); without any errors. Either way the file test is created.

Upvotes: 1

Related Questions