Reputation: 23
I need to open a file and get the first character.If I open the file with ios::in,it will not create a file when the file doesn't exist.So when it was failed to open the file, i open the file with ios::out
, it will creat a empty file, so i can input '0' to the file.
fstream passengerData;
passengerData.open("passenger.txt",ios::in);
if (!passengerData)
{
passengerData.open("passenger.txt",ios::out);
passengerData << '0' ;
passengerData.close();
}
When i run this in visual studio 2015
,it can work well.But in visual c++ 6.0
, it can only creat a empty file,the '0' is not input into the file.I want to know why the result is different and how to solve the problem.
I also want to know how the bitwise operator OR perform when i use ios::in|ios::out
or ios::in|ios::out|ios::app
.
Upvotes: 2
Views: 98
Reputation: 16070
The hunch that MicroVirus took on was right. I'd like to explain in detail why exactly nothing happened.
Basically, when passengerData.open("passenger.txt",ios::in);
the failbit
was set. Now you did retry with passengerData.open("passenger.txt",ios::out);
which did succeed (sic!), although the error bits were not cleared (pre-c++11 behaviour), and made the subsequent operator<<
do nothing.
I guess this was a flaw in the standard, and vc++6 is too old for c++11.
cppreference sources explaing the behaviour:
You use operator<<
, which is a FormattedOutputFunction
which says:
A FormattedOutputFunction is a stream output function that performs the following:
Constructs an object of type basic_ostream::sentry with automatic storage duration, which performs the following:
- if
eofbit
orbadbit
are set on the output stream, sets thefailbit
as well [...]
So it checks whether the stream (passengerData
) is operable. Now, interestingly enough, neither of eof
or bad
bits are set, so it seems like a wrong way, however the next step:
- Checks the status of the sentry by calling sentry::operator bool(), which is equivalent to
basic_ios::good
.
Which takes you those eof-
, fail-
, and bad-
bits. Those are iostate
s. In the failbit section you can find:
The failbit is set by the following standard library functions:
- The constructors of std::basic_fstream, std::basic_ifstream, and std::basic_ofstream that takes a filename argument, if the file cannot be opened.
- basic_fstream::open, basic_ifstream::open, and basic_ofstream::open if the file cannot be opened.
You can confirm this by checking the iostate
bits after 2nd open:
fstream passengerData;
passengerData.open("passenger.txt",ios::in);
if (!passengerData)
{
passengerData.open("passenger.txt",ios::out);
if (passengerData.rdstate() & std::ios_base::fail) {
std::cout << "stream has failbit set\n";
}
passengerData << '0' ;
passengerData.close();
}
Upvotes: 0
Reputation: 5477
From the documentation of fstream::open
on cppreference it seems that it's only since C++11 that open also clear()
s the flags on success, so maybe if you manually clear the flags before you call open
the call will also succeed in VC++6:
fstream passengerData;
passengerData.open("passenger.txt",ios::in);
if (!passengerData)
{
passengerData.clear();
passengerData.open("passenger.txt",ios::out);
passengerData << '0' ;
passengerData.close();
}
Also, you need to check the state of passengerData
after the second call to open
as well.
Upvotes: 3