(1) default constructor
Constructs an ofstream object that is not associated with any file.
Internally, its ostream base constructor is passed a pointer to a newly constructed filebuf object (the internal file stream buffer).
what happened to << when using ofstream without any filename pointed?
ofstream ofstream;
ofstream<<1<<endl;
where is the "1" go? is there any problems? I tried it, no issues. but I can't found any code clue for this, can anybody show the internal code explain for it?
Nothing happens.
[C++11: 27.9.1.1/3]: In particular:
If the file is not open for reading the input sequence cannot be read.
If the file is not open for writing the output sequence cannot be written.
A joint file position is maintained for both the input sequence and the output sequence
The stream is closed, an error flag is set and the data is ignored.
Example:
#include <iostream>
#include <fstream>
int main()
{
std::ofstream ofs;
ofs << 1 << std::endl;
std::cout << ofs.good() << std::endl;
}
// Output: 0
Live demo
The short version: the operations on the ofstream all fail, causing nothing to happen. The data that you write is lost and not stored anywhere, and the failbit will be set, causing the stream's fail() member function to return true.
The long version: when an ofstream is constructed without specifying a file, it default-constructs a filebuf. This creates a filebuf where is_open evaluates to false. As part of the stream insertion operation, the data to be written will need to be sent to the disk by calling filebuf::overflow, which, since is_open is false, will return EOF, causing the operation to fail.
Hope this helps!
Related
I was surprised to see my program suddenly go quiet when I added a cout at some point, so I isolated the responsible code:
std::stringstream data;
data<<"Hello World\n";
std:std::fstream file{"hello.txt", std::fstream::out};
file<<data.rdbuf();
std::cout<<"now rdbuf..."<<std::endl;
std::cout<<data.rdbuf()<<std::endl;
std::cout<<"rdbuf done."<< std::endl;
The program quietly exits without the final cout. What is going on? If I change the last .rdbuf() to .str() instead then it completes.
During the call to std::cout<<data.rdbuf(), std::cout is unable to read any characters from data's filebuf because the read position is already at the end of the file after the previous output; accordingly, this sets failbit on std::cout, and until this state is cleared any further output will fail too (i.e. your final line is essentially ignored).
std::cout<<data.str()<<std::endl; will not cause cout to enter a failed state because data.str() returns a copy of the underlying string regardless of where the read position is (for mixed-mode stringstreams anyway).
I am new to C++ and currently using visual studio.
I see on many tutorials online that when reading from a file with ifstream, before we cout the contents when looping through each line, we write the contents of the current line to a char data[] var then cout the data.
Something like the following
#include<iostream>
#include<fstream>
using namespace std;
int main()
{
ifstream f("D:\\file1.txt");
char a[80];
while(!f.eof())
{
f >> a;
cout << a << endl;
}
return(0);
}
What is the point of
char a[80];
...
f >> a;
cout << a << endl;
When we could just do
cout << f << endl;
And save declaring a char and wasting more lines of code?
The preferred method in C++ is:
#include<iostream>
#include<fstream>
int main()
{
std::ifstream f("D:\\file1.txt");
if( f )
{
std::string line;
while(getline(f, line) )
{
std::cout << line << endl;
}
}
return 0 ;
}
If you want to copy, or list files, use operating system commands. The operating system commands are more optimized for handling files. Also, they already exist and have been tested so you don't waste your time.
What is the purpose of storing the content in memory before printing it?
In your example, there isn't much of a point. The data being read from std::cin is being sent directly to std::cout to be displayed on the console. Generally, the only reasons you'd want to store the data in the program memory before printing it is if you want to modify the data or check properties of the data and take certain actions based on those properties.
It should be noted that while this is a common example, the use of while (!eof()) is the incorrect way to check the validity of the stream before reading data. This method checks the stream before the input is read, which can lead to undefined behavior if invalid data is read and subsequently used. The normal way to read data is to check the validity of the stream after performing the read. For example, in your program this would be changed to:
while (f >> a)
{
std::cout << a << std::endl;
}
After the read is performed, the stream will be converted to a boolean. It will return true or false depending on the validity of the stream. If the stream read the end-of-file (EOF) character then that would be a failed read and the stream will return false.
What is the point of
char a[80];
...
f >> a;
cout << a << endl;
when we could just do
cout << f << endl;
First, cout << f will not do what you expect. The stream insertion operator (operator<<()) is overloaded for certain types. f is of type std::ifstream - a type for which this operator is not overloaded. Pre-C++11 C++ IOStreams contained a conversion to void* so that they could be used in boolean contexts. The stream insertion operator is overloaded for pointers to void, so the output you would get is not something you'd expect. As of C++11 you'd get a compiler error that no operator overload could be found for that type.
There is, however, an overload for std::streambuf*, a pointer an IOStreams buffer. Each stream has a buffer that stores and maintains characters from the source or sink. The overload for this operator reads data from the buffer and sends it to its own buffer, so you can do something like this:
std::cout << f.rdbuf();
rdbuf() returns a pointer to the stream's buffer.
While this is an effective use of the stream's capabilities, the data is still being stored in the buffer of std::cout. Streams are buffered and data sent into the source or sink are consigned to a buffer where it waits until the buffer is flushed. You can use std::nounitbuf to unbuffer std::cout in order to write directly to the external device:
std::cout << std::nounitbuf
<< f.rdbuf();
For a simple example with a small file, buffering really isn't needed. If you have a very large file then buffering is very useful as the program doesn't have to make a system call for each character being inserted.
Can someone explain the subtle difference in:
ofstream f("test.txt")
std::stringstream s;
s<<"";
f << s.rdbuf();
f.good() // filestream is bad!!
ofstream f("test.txt")
std::stringstream s;
s<<"";
f << s.str();
f.good() // is still ok!
I mostly use .rdbuf() to push the stringstream to the file (because its more efficient), but if the stringstream is empty than the filestream gets bad...? Isnt this stupid?
I think I dont quite understand << s.rdbuf() ...
The insertion operator that "inserts" streambuffers sets the failbit if no characters could be extracted from the streambuffer - [ostream.inserters]/9:
If the function inserts no characters, it calls setstate(failbit)
(which may throw ios_base:: failure (27.5.5.4)).
Whereas the insertion operator that outputs a string obviously doesn't consider the amount of characters written.
It seems that this is because inserting a streambuffer "forwards" the streambuffer into the stream - if no characters could be extracted most certainly there was an error in the streambuffer itself and this error should be represented by the streams error state. Outputting an empty stream is an exception that was presumably not considered important enough to take into account when this rule was created.
I recently used fstream for a homework assignment and I was wondering about how two things worked.
#include <iostream>
#include <fstream>
using namespace std;
int main(int argc, char** argv) {
ifstream myFile;
myFile.open("fileone.txt");
int myInt = 0;
while (myFile.good()) { // What is the difference between myFile and myFile.good()?
if (!myFile.eof()){
myFile >> myInt;
cout << myInt << endl;
}
}
return 0;
}
This is a snippet of my actual code I am working on. In another post, someone said that if I used while(myFile) , it would automatically convert into a bool. What is the difference between using this and using the member function .good() of the ifstream class? I know that .good() breaks out of the while loop when I reach the end of the text file but how does using the stream name behave?
IOStream classes have 4 functions for assessing the stream state: good(), bad(), fail(), and eof(). Excluding good(), each function checks a single bit in the underlying stream state and returns whether or not the bit is on (are there errors?). good() in particular checks if all the bits are off (is the stream valid?). These are what they are for:
good(): The stream has not encountered an error.
bad(): The stream has encountered an error that effects the integrity of the stream (i.e memory allocation failure, no buffer, etc.)
fail(): Typically a recoverable error (formatting/parsing failure).
eof(): The end-of-file (EOF) character has been reached.
When performing I/O, it is integral that you check for errors in the stream while processing input. What novices typically don't know is that the only function that was meant to be used to check for valid input is fail(). All the other functions are useful in other cases but not for conditioning input.
Futhermore, novices also fail to realize that input must be performed before checking for errors. Doing otherwise allows an unchecked extraction, allowing the body of the loop to access the value that was not produced from a valid extraction.
Streams have a boolean operator that returns !fail(), this allows you to check the stream in an elegant way after performing input, like this:
while (myFile >> myInt) {
// ...
}
This is the best way to perform input. The extraction itself should be present within a conditional context so that the body of whatever its being used in is executed only if the extraction succeeded.
Read the manual.
The bool conversion is defined so that the following are the same:
if (stream) { ... }
if (!stream.fail()) { ... }
There is a difference between stream.good() and !stream.fail(): !fail is also true the end of file.
And one more big issue with your code: you should check if the read is successful before using the input. So this is really bad:
myFile >> myInt;
cout << myInt << endl
because you have not checked if you really succeeded to read an int into myInt.
TLDR:
Use this for reading ints from a file:
while (myFile >> myInt) {
cout << myInt << endl;
}
Reason: myFile >> myInt returns myFile so it will invoke the bool conversion which should be used as the loop condition.
Any idea why the following would fail?
std::fstream i(L"C:/testlog.txt", std::ios::binary | std::ios::in);
int test = 0;
i >> test;
fail() is returning true. The file exists and is opened.
I checked
i._Filebuffer._Myfile._ptr
and it is pointer to a buffer of the file so I don't see why it is failing.
You're opening the file in binary mode. The extraction operators were meant to be used with text files. Simply leave out the std::ios::binary flag to open the file in text mode.
If you actually do have a binary file, use the read() function instead.
Edit: I tested it too, and indeed it seems to work. I got this from CPlusPlus.com, where it says:
In binary files, to input and output data with the extraction and insertion operators (<< and >>) and functions like getline is not efficient, since we do not need to format any data, and data may not use the separation codes used by text files to separate elements (like space, newline, etc...).
Together with the description of ios::binary, which simply states "Consider stream as binary rather than text.", I'm utterly confused now. This answer is turning into a question of its own...
The following:
#include <fstream>
#include <iostream>
using namespace std
int main() {
std::fstream i("int.dat" , std::ios::binary | std::ios::in);
int test = 0;
if ( i >> test ) {
cout << "ok" << endl;
}
}
prints "ok" when given a file containing the characters "123". Please post a similar short test that illustrates your code failing.