Discrimination between file and console streams - c++

How to determine weather ostream is a file or a console stream. In the following program I want to print "Hello file!" while writing to a file and "Hello console!" while writing to console. What condition should I specify at 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"
}

Maybe not pretty, 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 the Standard output might be redirected to file, so I think it is better to use the streambuf object instead. (See this answer for better understanding as to how the redirection works, and why comparing streambuf solves the problem safely! )

You could (ab)use tellp(), which returns -1 if the stream does not have a position:
bool isConsoleStream(ostream const& stream)
{
return stream.tellp() == -1;
}
Of course, there could be other streams that return -1 for this function, so use with caution.

There is no portable means. Under Unix, you can do:
if ( (&os == &std::cout && isatty( STDOUT ))
|| (&os == &std::cerr && isatty( STDERR ))
|| (&os == &std::clog && isatty( STDERR )) ) }
// is a terminal...
}
Under Windows, the isatty becomes _isatty, and I'm not sure
that the macros exist (but I suspect that they do).
Of course, this supposes that you don't do things 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 it's about as close as you can get without the actual fd
from the filebuf.

One is a ofstream and the other is a ostream. Just have 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;
}

This works on Visual Studio 2012
if (typeid(os) == typeid(ofstream)) //this is line 17
But an ostream could be something that isn't an ofstream or the console so you'd have to be careful.

Function to check if a C++ character stream is connected to a terminal/console/tty.
Ideally, we would use the file descriptor under-laying the stream buffer of the C++ stdio stream (cin, cout, cerr or clog).
However, there is no way to retrieve the under-laying file descriptor.
So, we use the fact that at program start-up the stdio stream buffers are connected to the program's standard input and output.
This function only works under the following conditions:
The stream buffers of the start-up C++ stdio streams must not change.
Because the addresses of the stream buffers of the start-up C++ stdio streams are used as identifiers.
For instance by deleting them and then allocating a new stream buffer that has the same address as one of these stream buffers of the start-up C++ stdio streams.
The program's stdio must not change after program start-up.
Because the TTY statuses of the stdio stream buffers are stored at program start-up.
For instance if at start-up the std. out is connected to a terminal and later it is redirected to a pipe or file by something external to the program.
[Instead of storing the TTY statuses at start-up you could retrieve them at run-time, but then you must make sure that your program (and all libraries it uses) does not change the stdio file descriptors (0, 1 and 2). Rember that the stdio stream buffers most likely use other (duplicate) file descriptors.]
Code:
#include <iostream>
extern "C" {
#ifdef _WIN32
# include <io.h> // for: _isatty()
#else
# include <unistd.h> // for: isatty()
#endif
}
// Stdio file descriptors.
#ifndef STDIN_FILENO
# define STDIN_FILENO 0
# define STDOUT_FILENO 1
# define STDERR_FILENO 2
#endif
// Store start-up addresses of C++ stdio stream buffers as identifiers.
// These addresses differ per process and must be statically linked in.
// Assume that the stream buffers at these stored addresses
// are always connected to their underlaying stdio files.
static const streambuf* const StdioBufs[] = {
std::cin.rdbuf(), std::cout.rdbuf(), std::cerr.rdbuf(), std::clog.rdbuf()
};
static const wstreambuf* const StdioWBufs[sizeof(StdioBufs)/sizeof(StdioBufs[0])] = {
std::wcin.rdbuf(), std::wcout.rdbuf(), std::wcerr.rdbuf(), std::wclog.rdbuf()
};
// Store start-up terminal/TTY statuses of C++ stdio stream buffers.
// These statuses differ per process and must be statically linked in.
// Assume that the statuses don't change during the process life-time.
static const bool StdioTtys[sizeof(StdioBufs)/sizeof(StdioBufs[0])] = {
#ifdef _WIN32
_isatty(STDIN_FILENO), _isatty(STDOUT_FILENO), _isatty(STDERR_FILENO), _isatty(STDERR_FILENO)
#else
isatty(STDIN_FILENO), isatty(STDOUT_FILENO), isatty(STDERR_FILENO), isatty(STDERR_FILENO)
#endif
};
// Is a Terminal/Console/TTY connected to the C++ stream?
// Use on C++ stdio chararacter streams: cin, cout, cerr and clog.
bool isTTY(const ios& strm)
{
for(unsigned int i = 0; i < sizeof(StdioBufs)/sizeof(StdioBufs[0]); ++i) {
if(strm.rdbuf() == StdioBufs[i])
return StdioTtys[i];
}
return false;
}
// Is a Terminal/Console/TTY connected to the C++ stream?
// Use on C++ stdio wide-chararacter streams: wcin, wcout, wcerr and wclog.
bool isTTY(const wios& strm)
{
for(unsigned int i = 0; i < sizeof(StdioWBufs)/sizeof(StdioWBufs[0]); ++i) {
if(strm.rdbuf() == StdioWBufs[i])
return StdioTtys[i];
}
return false;
}
Note: I've only tested it on Linux.

Related

std::istream does not call xsgetn() on read operations?

I want to be notified when a file associated with a std::istream is read from using the istream and the same with an ostream being written to. With this in mind I decided to try deriving my own std::basic_filebuf, and just to experiment I tried to override the xsgetn() and xsputn() functions so that they would output to the console before calling the parent implementation:
#include <iostream>
#include <fstream>
#include <cstdio>
class MyFileBuff : public std::filebuf
{
public:
std::streamsize xsgetn(char_type* s, std::streamsize count) override
{
std::cout << "using my xsgetn()" << std::endl;
return std::filebuf::xsgetn(s, count);
}
std::streamsize xsputn(const char_type* s, std::streamsize count) override
{
std::cout << "using my xsputn()" << std::endl;
return std::filebuf::xsputn(s, count);
}
using std::filebuf::basic_filebuf;
};
int main()
{
//open file
FILE* filePtr{ nullptr };
fopen_s(&filePtr, "text.txt", "w+");
//associate file with instance of custom std:filebuff
MyFileBuff fileBuff(filePtr);
//initalize i/o streams with file buffer
std::istream myIStream(&fileBuff);
std::ostream myOStream(&fileBuff);
//output to file
myOStream << "hello world" << std::endl;
const short buffSize{ 1024 };
char buff[buffSize];
myIStream.seekg(0);
//read from file
myIStream.getline(buff, buffSize);
//output what was read to console
std::cout << buff << std::endl;
return 0;
}
This outputs:
> using my xsputn()
> hello world
As you can see, my override of xsputn() is called on the write operation. But despite the read operation completing successfully, my override of xsgetn() is never called. I would like help understanding why.
I have also tried overloading the std::basic_filebuf::uflow() and std::basic_filebuf::underflow() functions in a similar manner and they do successfully output to the console when the istream is read, but I don't understand why xsgetn() never gets called?

Check what output is written to standard output

I want to check whether output is written to the standard output (through cout) in a certain part of my program.
What I found is a way to block any output by changing the streambuf of cout. (here:C++: Redirecting STDOUT). That is interesting and first I thought it might help. I found the following code example (source: answer to C++: Redirecting STDOUT)
// Redirect cout.
streambuf* oldCoutStreamBuf = cout.rdbuf();
ostringstream strCout;
cout.rdbuf( strCout.rdbuf() );
// This goes to the string stream.
cout << "Hello, World!" << endl;
// Restore old cout.
cout.rdbuf( oldCoutStreamBuf );
// Will output our Hello World! from above.
cout << strCout.str();
So I can just check whether strCout.str() is a string with 1 or more characters by checking its size.
But what if I do not want to delay the output significantly? So I do not want to save all output in my own ostringstream, wait until I checked whether there was output at the end of my program and then print all the output shortly before my programm ends. I just want to know, whether there was output in a certain part of my program.
Example:
main {
bool wasthereoutput=false;
function1();
function2();
startoutputcheckhere();
function3();
function4();
endoutputcheckhere();
therewasoutput=wasthereoutput();
if therewasoutput{
//do something
}
I don't want to change anything in function3 or function4. I do not want to delay any output generated by those functions until i call endoutputcheckhere() or even wasthereoutput(). I just want to know if there was any output going to std output through cout.
You can create a stream buffer which both collects the written characters for later and also forwards them to another stream buffer, e.g., the one used by std::cout. A simple implementation of this approach could look like this:
class savebuf:
public std::streambuf {
std::streambuf* sbuf;
std::string save;
int overflow(int c) {
if (!traits_type::eq_int_type(c, traits_type::eof()) {
save.push_back(traits_type::to_char_type(c);
return sbuf->sputc(c);
}
else {
return traits_type::not_eof(c);
}
}
int sync() { return sbuf->pubsync(); }
public:
savebuf(std::streambuf* sbuf): sbuf(sbuf) {}
std::string str() const { return save; }
};
int main() {
std::streambuf* coutbuf = std::cout.rdbuf();
savebuf sbuf(coutbuf);
std::cout.rdbuf(&sbuf);
std::cout << "Hello, world\n";
std::cout.rdbuf(coutbuf); // restore the original stream buffer
std::cout << "saved \"" << sbuf.str() << "\"\n";
}
Note that you should restore std::cout's stream buffer as the stream buffer is flushed (i.e. pubsync() is called on it) when std::cout is sort of destroyed.

Is there a way to switch on/off std:cerr (or equivalent)?

Without using a full-blown logging library (or IF statements) - is there a way in C++ to sometimes print out messages to the console and sometimes not?
I am using std::cerr, is there a way to control when this outputs or not?
Ideally I could have:
std::cerr << "Constructor called" << endl;
and have a way to enable/disable this line of code?
I am not sure what you mean by "without if", but you can write code without using the if yourself. A macro can check a flag for you.
#define CERR if (cerr_disabled) {} else std::cerr
bool cerr_disabled = false;
Then, in your code:
CERR << "error message" << std::endl;
If cerr_disabled is true, then nothing is printed.
The advantage of this macro approach is that none of the print arguments get evaluated if the err logging is disabled. For instance, if you needed to call a function to create a more complicated log string:
std::string fancy_log_message () {
//...
}
CERR << fancy_log_message();
If cerr_disabled is true, fancy_log_message() is not called. This is something that can't be achieved by just suppressing the stream object itself.
The simple approach is to set/clear std::ios_base::failbit on the stream: while std::ios_base::failbit is set, the streams won't do any work [unless the output operators are written incorrectly]:
std::cerr.setstate(std::ios_base::failbit);
std::cerr << "this won't show\n";
std::cerr.clear();
std::cerr << "this will show!\n";
To make these operations easier to use you can create manipulators, e.g.:
std::ostream& stream_on(std::ostream& out) {
out.clear();
return out;
}
std::ostream& stream_off(std::ostream& out) {
out.setstate(std::ios_base::failbit);
return out;
}
std::cerr << stream_off << "not printed\n" << stream_on << "printed\n";
If you really want to disable the stream even if the output operators are badly implemented, you can save the current rdbuf() (e.g., in a suitable std::ostream::pword()) and set the stream buffer to nullptr:
static int stream_off_index() { static int rc = std::ios_base::xalloc(); return rc; }
std::ostream& stream_on(std::ostream& out) {
out.pword(stream_off_index) = out.rdbuf(nullptr);
return out;
}
std::ostream& stream_off(std::ostream& out) {
if (!out.rdbuf()) {
out.rdbuf(out.pword(stream_off_index);
}
return out;
}
Here is a solution without macros:
#include <iostream>
void toggle_cerr()
{
static std::streambuf* p = std::cerr.rdbuf();
std::cerr.rdbuf(std::cerr.rdbuf() ? nullptr : p);
}
int main()
{
toggle_cerr();
std::cerr << "str";
}

How to override cout in C++?

I have a requirement, I need to use printf and cout to display the data into console and file as well.
For printf I have done it but for cout I am struggling, how to do it?
#ifdef _MSC_VER
#define GWEN_FNULL "NUL"
#define va_copy(d,s) ((d) = (s))
#else
#define GWEN_FNULL "/dev/null"
#endif
#include <iostream>
#include <fstream>
using namespace std;
void printf (FILE * outfile, const char * format, ...)
{
va_list ap1, ap2;
int i = 5;
va_start(ap1, format);
va_copy(ap2, ap1);
vprintf(format, ap1);
vfprintf(outfile, format, ap2);
va_end(ap2);
va_end(ap1);
}
/* void COUT(const char* fmt, ...)
{
ofstream out("output-file.txt");
std::cout << "Cout to file";
out << "Cout to file";
}*/
int main (int argc, char *argv[]) {
FILE *outfile;
char *mode = "a+";
char outputFilename[] = "PRINT.log";
outfile = fopen(outputFilename, mode);
char bigfoot[] = "Hello
World!\n";
int howbad = 10;
printf(outfile, "\n--------\n");
//myout();
/* then i realized that i can't send the arguments to fn:PRINTs */
printf(outfile, "%s %i",bigfoot, howbad); /* error here! I can't send bigfoot and howbad*/
system("pause");
return 0;
}
I have done it in COUT(caps, the commented part for the code above) . But I want to use normal std::cout, so how can I override it. And it should work for both sting and variables like
int i = 5;
cout << "Hello world" << i <<endl;
Or are there anyway to capture stdout data, so that they can be easily written into file and console as well.
If you have another stream buffer, you can just replace std::cout's:
std::cout.rdbuf(some_other_rdbuf);
See http://en.cppreference.com/w/cpp/io/basic_ios/rdbuf.
You can swap the underlying buffers. Here is that done facilitated through RAII.
#include <streambuf>
class buffer_restore
{
std::ostream& os;
std::streambuf* buf;
public:
buffer_restore(std::ostream& os) : os(os), buf(os.rdbuf())
{ }
~buffer_restore()
{
os.rdbuf(buf);
}
};
int main()
{
buffer_restore b(std::cout);
std::ofstream file("file.txt");
std::cout.rdbuf(file.rdbuf());
// ...
}
Overriding the behaviour of std::cout is a really bad idea as other developers will have a hard time understanding that the use of std::cout doesn't behave as usual.
Make your intention clear with a simple class
#include <fstream>
#include <iostream>
class DualStream
{
std::ofstream file_stream;
bool valid_state;
public:
DualStream(const char* filename) // the ofstream needs a path
:
file_stream(filename), // open the file stream
valid_state(file_stream) // set the state of the DualStream according to the state of the ofstream
{
}
explicit operator bool() const
{
return valid_state;
}
template <typename T>
DualStream& operator<<(T&& t) // provide a generic operator<<
{
if ( !valid_state ) // if it previously was in a bad state, don't try anything
{
return *this;
}
if ( !(std::cout << t) ) // to console!
{
valid_state = false;
return *this;
}
if ( !(file_stream << t) ) // to file!
{
valid_state = false;
return *this;
}
return *this;
}
};
// let's test it:
int main()
{
DualStream ds("testfile");
if ( (ds << 1 << "\n" << 2 << "\n") )
{
std::cerr << "all went fine\n";
}
else
{
std::cerr << "bad bad stream\n";
}
}
This provides a clean interface and outputs the same for both the console and the file.
You may want to add a flush method or open the file in append mode.
I assume you have some code using std::cout and printf which you cannot modify, otherwise the most simple way to solve your problem would be to write to a different stream from cout and use fprintf rather than or in conjunction with printf.
By following that approach you could define both a new stream class that actually wrote both to standard output and to a given file, as well as a function that combined calls to both printf and fprintf.
However a much simpler approach is to use the tee program, originally from UNIX, which copies its input both to output and to a given file. With that you could simply call your program in this way:
your_program | tee your_log_file
Answers to this question lead to a few alternative implementations available for Windows. Personally I always install cygwin on my PC's to have UNIX/Linux utilities available.
If i guess correctly you want to log everything that goes to the output also into a file.
What you want is an observer pattern.
Replace all direct logging in your code with calls to a new relay.
The logging relay sends your messages to the observers.
One of your observers loggs the message to the screen.
The other one loggs to the file.
Avoid making your relay a singleton if possible.
This suggestion only works if you can edit all of your source files.
std::cout writes to stdout file you can do the following on Linux and Windows
#include <stdio.h>
#include <iostream>
int main()
{
freopen("test.txt", "w", stdout);
std::cout << "Hello strange stdout\n";
}
to change it back use the following taken from here
#include <stdio.h>
#include <stdlib.h>
void main(void)
{
FILE *stream ;
if((stream = freopen("file.txt", "w", stdout)) == NULL)
exit(-1);
printf("this is stdout output\n");
stream = freopen("CON", "w", stdout);
printf("And now back to the console once again\n");
}
Note: The latter is windows only
cout is normally implemented as an object instance so you can't override it in the way that you would overload / override a function or a class.
Your best bet is not to fight that - yes you could build a my_cout and #define cout my_cout but that would make your code obtuse.
For readability I'd leave cout as it is. It's a standard and everyone knows what it can and can't do.
Try using a macro - something like this (you'll need to add the includes) :
#define MY_COUT(theos,printThis) { cout << printThis ; theos << printThis; }
void test()
{
ofstream myos;
myos.open("testfile", ios::trunc|ios::out);
int i = 7;
MY_COUT(myos, "try this numbers" << i << i + 1 << endl);
myos.close()
}
There's already a Boost class for this: tee

Checking to see if ofstream is empty?

I've created an ofstream and there is a point in which I need to check if it's empty or has had things streamed into it.
Any ideas how I would go about doing this?
The std::ofstream files don't support this directly. What you can do if this is an important requirement is to create a filtering stream buffer which internally used std::filebuf but also records if there was any output being done. This could look look as simple as this:
struct statusbuf:
std::streambuf {
statusbuf(std::streambuf* buf): buf_(buf), had_output_(false) {}
bool had_output() const { return this->had_output_; }
private:
int overflow(int c) {
if (!traits_type::eq_int_type(c, traits_type::eof())) {
this->had_output_ = true;
}
return this->buf_->overflow(c);
}
std::streambuf* buf_;
bool had_output_;
};
You can initialize an std::ostream with this and query the stream buffer as needed:
std::ofstream out("some file");
statusbuf buf(out.rdbuf());
std::ostream sout(&buf);
std::cout << "had_output: " << buf.had_output() << "\n";
sout << "Hello, world!\n";
std::cout << "had_ouptut: " << buf.had_output() << "\n";
you could use ofstream.rdbuff to get the file buffer and than use streambuf::sgetn to read it. I believe that should work.