Discrimination between file and console streams

How to determine weather ostream is a file or console stream. In the next program, I want to print "Hello file!" when writing to a file and "Hello console!". when recording to the console. Which condition should be indicated on line 17?

#include <fstream> #include<iostream> #include <string> using namespace std; class A{ public: A(string msg):_str(msg){} string str()const {return _str;}; private: string _str; }; ostream & operator << (ostream & os, const A & a) { if (os is ofstream) //this is line 17 os << "Hello file! " << a.str() << endl; else os << "Hello console! " << a.str() << endl; return os; } int main() { A a("message"); ofstream ofile("test.txt"); if (!ofile) cerr << "Unable to open file"; else ofile << a; // "Hello file" cout << a << endl; // "Hello console" } 
+8
c ++ ostream fstream
source share
5 answers

Maybe not very, but

 std::streambuf const * coutbuf = std::cout.rdbuf(); std::streambuf const * cerrbuf = std::cerr.rdbuf(); ostream & operator << (ostream & os, const A & a) { std::streambuf const * osbuf = os.rdbuf(); if ( osbuf == coutbuf || osbuf == cerrbuf ) os << "Hello console! " << a.str() << endl; else os << "Hello file! " << a.str() << endl; return os; } 

We could use &os == &std::cout , but Standard output can be redirected to a file, so I think it's better to use the streambuf object. (See this answer for a better understanding of how redirection works and why streambuf comparisons safely solve the problem!)

+4
source share

You can (ab) use tellp() , which returns -1 if the stream has no position:

 bool isConsoleStream(ostream const& stream) { return stream.tellp() == -1; } 

Of course, there may be other threads that return -1 for this function, so use with caution.

+3
source share

One is ofstream and the other is ostream . Just use two methods.

 #include <iostream> #include <string> #include <fstream> class A { std::string s; public: A(const std::string& s) : s(s){} std::string str() const {return s;} }; ostream & operator << (std::ostream & os, const A & a) { return os << "console: " << a.str() << std::endl; } ofstream & operator << (std::ofstream & os, const A & a) { return os << "file: " << a.str() << std::endl; } int main() { A a("hello world"); std::cout << a << endl; } 
+2
source share

There are no portable devices. On Unix, you can:

 if ( (&os == &std::cout && isatty( STDOUT )) || (&os == &std::cerr && isatty( STDERR )) || (&os == &std::clog && isatty( STDERR )) ) } // is a terminal... } 

On Windows, isatty becomes _isatty , and I'm not sure if macros exist (but I suspect that they do).

Of course, this assumes that you are not doing something to confuse it in your code. Something like:

 std::ostream s( std::cout.rdbuf() ); 

for example: or

 std::cout.rdbuf( &someFileBuf ); 

Or even:

 std::ofstream s( "/dev/tty" ); // (or "CONS" under Windows). 

But this is about as close as you can get without actual fd from filebuf .

+2
source share

This works on Visual Studio 2012

 if (typeid(os) == typeid(ofstream)) //this is line 17 

But ostream may be something that is not a stream or console, so you need to be careful.

0
source share

All Articles