20

I have a small program where i initialize a string and write to a file stream:

#include<iostream>
#include<fstream>
using namespace std;
int main()
{
  std::ofstream ofs(file.c_str());
  string s="Hello how are you";
  if(ofs)
     ofs<<s;
  if(!ofs)
  {
       cout<<"Writing to file failed"<<endl;
  }
  return 0;
 }

My diskspace is very less, and the statement "ofs<" fails. So I know that this is an error logically.

The statement "if(!ofs)" does not encounter the above issue, hence I am unable to know why it failed.

Please tell me, by which other options I would be able to know that "ofs< has failed.

Thanks in advance.

Santosh Sahu
  • 2,134
  • 6
  • 27
  • 51
  • Have you checked that the `ofstream` is actually open before trying to `ofs <<`? – Emil Laine Feb 05 '15 at 11:25
  • `ofstream::operator<<` will modify the internal state flags if it fails. Have you checked `ofstream::eof`/`bad`/`fail`? – Emil Laine Feb 05 '15 at 11:31
  • @zenith: internal state flags will change if it fails to open the file. can you confirm if it fails while writing also? Request you to please show some cod e if possible. – Santosh Sahu Feb 05 '15 at 11:36
  • Check the _Return value_ section [here](http://www.cplusplus.com/reference/ostream/ostream/operator%3C%3C/). Does that answer your question? – Emil Laine Feb 05 '15 at 11:45
  • @zenith `ofstream::operator<<` will fail if there is a write error when attempting to write the data. Because of buffering, this will generally not be on the output operation which fails. _Usually_, it is sufficient to verify the status of the `ofstream` after `close` (when it is guaranteed that all data have been flushed); if you need a timely check, then you must flush the stream first. – James Kanze Feb 05 '15 at 12:07
  • @zenith Well, it does't really specify what is meant by an error. Buffering can easily cause the error state to be deferred. – James Kanze Feb 05 '15 at 12:09
  • And while I'm at it: verifying that output has succeeded is really one of the most basic elements of output in general. A tutorial which doesn't insist on checking the output stream, at least after the close, is very deficient. – James Kanze Feb 05 '15 at 12:11
  • The most important point, of course, is that you cannot depend on the close in the destructor of `std::ofstream`; you must explicitly close the stream and test the status _after_ having closed it. – James Kanze Feb 05 '15 at 12:13

2 Answers2

25

In principle, if there is a write error, badbit should be set. The error will only be set when the stream actually tries to write, however, so because of buffering, it may be set on a later write than when the error occurs, or even after close. And the bit is “sticky”, so once set, it will stay set.

Given the above, the usual procedure is to just verify the status of the output after close; when outputting to std::cout or std::cerr, after the final flush. Something like:

std::ofstream f(...);
//  all sorts of output (usually to the `std::ostream&` in a
//  function).
f.close();
if ( ! f ) {
    //  Error handling.  Most important, do _not_ return 0 from
    //  main, but EXIT_FAILUREl.
}

When outputting to std::cout, replace the f.close() with std::cout.flush() (and of course, if ( ! std::cout )).

AND: this is standard procedure. A program which has a return code of 0 (or EXIT_SUCCESS) when there is a write error is incorrect.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • does your statement regarding EXIT_FAILURE mean that it is unsafe for a program to continue after a write error? I should think it is unsafe, but I just want to be extra sure. – batbrat Feb 21 '17 at 06:56
  • 1
    @batbrat No. He means that a program should not return `0` (_i.e._ success) when there's been a problem. – n.caillou Aug 03 '17 at 23:17
  • 2
    @n.caillou Good point. We can return success when a problem occurs, if and only if we have handled it completely, right? – batbrat Aug 04 '17 at 09:54
  • 2
    But how can we get a useful information about why write failed? – kroiz Sep 22 '19 at 12:28
  • why replace close with flush?? – Boppity Bop Apr 14 '22 at 12:19
6

I found a solution like

#include<iostream>
#include<fstream>
using namespace std;
int main()
{
  std::ofstream ofs(file.c_str());
  string s="Hello how are you";
  if(ofs)
     ofs<<s;
  if(ofs.bad())    //bad() function will check for badbit
  {
       cout<<"Writing to file failed"<<endl;
  }
  return 0;
 }

You can also refer to the below links here and thereto check for the correctness.

Santosh Sahu
  • 2,134
  • 6
  • 27
  • 51
  • 7
    I would be very surprised if this worked. You must either close the stream or flush it for the error to be detected. – James Kanze Feb 05 '15 at 12:14
  • 1
    Is there any chance that the stream is flushed when a lot of input has been written to the buffer? In that case, this might be a worthwhile check to add so that the program can terminate as soon as the error is noticed. – batbrat Feb 21 '17 at 06:59
  • What does the `if (ofs)` do? I would expect that condition to be always true, since `ofs` is an object on the stack. – jvriesem May 02 '20 at 20:20
  • 2
    @jvriesem Probably a bit late, but in the case that the file couldn't be created in the constructor "std::ofstream ofs(file.c_str())", the object will be null and that's what is checked in the if – Cypert Jun 05 '20 at 22:11
  • bad() will check only badbit, why not fail()? It is checking badbit or failbit both. – Build Succeeded Sep 04 '20 at 08:17