Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Redirect cout to file

3,123 views
Skip to first unread message

DREMTIME98

unread,
Oct 12, 1999, 3:00:00 AM10/12/99
to
Yeah hello everyone. First , I just want to say thanks to all those good
people who answer questions on this board. Really you guys are alright.
Sometimes I try to answer questions on some of the more newbie sites(where I
CAN answer) and I find that even a relatively simple question can take me more
than half an hour to answer(could also be due to the fact that I am a little
simple minded) Some of the questions you get here are a lot more involved and
take much more time. A lot of you guys give up a lot of your time and I just
want to say hats off to you guys. what you do is selfless and kind and I think
we should all appreciate it before it's gone. There really cant be any other
motive than simple kindness. Gee I've moved myself to tears! Now I need a
hanky.
(ok ok I know it's a little mushy -after all we are talking c++ honchos etc,say
is that like being Macho with a computer or something? Well dont get offended
I just want to acknowledge all the do gooders Hey in a world like this they
deserve it once in a while.)

Now to my question. I wonder how I might be able to direct cout to not only
print to the screen but also write to a file. How do you use redirection for
that?

Thanks a lot
Jim.

Jim Cobban

unread,
Oct 12, 1999, 3:00:00 AM10/12/99
to
DREMTIME98 wrote:

> Now to my question. I wonder how I might be able to direct cout to not only
> print to the screen but also write to a file. How do you use redirection for
> that?

File redirection is a function of the command shell, not of C++. You need to
examine which command shell you are using. The command shell that comes with
Windows does not support the function that you are looking for. The command shells
for UNIX do support it. If you are on Windows you can get the bash shell from
various places to use in place of COMMAND.COM.

--
Jim Cobban jco...@magma.ca
34 Palomino Dr.
Kanata, ON, CANADA
K2M 1M1
+1-613-592-9438

thesnaguy.vcf

TiTi

unread,
Oct 13, 1999, 3:00:00 AM10/13/99
to
Don't use cout, use a file output stream.

TiTi

Dietmar Kuehl

unread,
Oct 13, 1999, 3:00:00 AM10/13/99
to dremt...@aol.com
Hi,
In article <19991012134236...@ng-fz1.aol.com>,

dremt...@aol.com (DREMTIME98) wrote:
> There really cant be any other motive than simple kindness.

Read "Homesteeding the Noosphere" by Eric Raymond (you should find this
paper on his homepage which in turn can be found via
<http://www.opensource.org/>). Apart from mere kindness, this describes
more motives, at least it describes some motivation which I can find for
myself. I have also other motives which are rather commercial: You can
sell a good reputation.

> Now to my question. I wonder how I might be able to direct cout to
> not only print to the screen but also write to a file. How do you use
> redirection for that?

I'm not clear how you really want to redirect 'cout' but since you are
posting to a C++ newsgroup I'm assuming that you don't want to use the
shell redirection mechanism (eg. on POSIX systems something like
"program | tee file"; see the man page of tee(1) for more information).
Instead, I'm assuming you want to use only C++ mechanisms.

Your question actually consists of two separate parts:
- How to redirect 'std::cout'?
- How to write to more than one stream at once?

The answer to the first question is to pass around a reference to an
'std::ostream' and write to this stream. In this case you would just
pass 'std::cout' from something like 'main()' and that's it. Sometimes
this is not appropriate, eg. because the code is mostly already existing
and uses 'std::cout' all over. In this case you can just replace the
stream buffer used by 'std::cout' with a suitable other stream buffer.
Since this question is answered first, I'm just directing 'std::cout' to
a file. It can as well be directed to the stream buffer described below:

int main() {
std::streambuf* cout_sbuf = std::cout.rdbuf(); // save original sbuf
std::ofstream fout("cout.txt");
std::cout.rdbuf(fout.rdbuf()); // redirect 'cout' to a 'fout'
// ...
std::cout.rdbuf(cout_sbuf); // restore the original stream buffer
}

Restoring the original stream buffer is necessary because the stream
buffer to which 'std::cout' was redirected is destroyed at the end of
'main()'. Thus, writing stuff to 'std::cout' after exiting from 'main()'
that is from a destructor of an object with static linkage would fail.
Restoring the original stream buffer avoids this problem.

This was easy so far. Now for the more interesting part of writing to
multiple destinations at once: This is done using a new stream buffer
which writes to two destinations. To do so, the new stream buffer, call
it 'teebuf', writes to two stream buffers it gets at construction time.
For simplicity, the buffer in the example is unbuffered but for better
performance it is reasonable to add a buffer (this would, however, make
the code significantly more complex):

#include <streambuf>
class teebuf: public std::streambuf {
public:
typedef std::char_traits<char> traits_type;
typedef traits_type::int_type int_type;

teebuf(std::streambuf* sb1, std::streambuf* sb2):
m_sb1(sb1), m_sb2(sb2) {}
private:
int_type overflow(int_type c) {
if (!traits_type::eq_int_type(c, traits_type::eof()) {
c = sb1->sputc(c);
if (!traits_type::eq_int_type(c, traits_type::eof()))
c = sb2->overflow(c);
return c;
}
else
return traits_type::not_eof(c);
}
int sync() {
int rc = sb1->sync();
if (rc != -1)
rc = sb2->sync();
return rc;
}
};

This is a very simple unbuffered write-only stream buffer. Every
received character is immediately sent to the two underlying stream
buffers: If the method 'sputc()' cannot put a character into the buffer,
it calls 'overflow()' to write this character and give the stream buffer
a chance to set up a new buffer. Since there is no buffer to be set up,
the character is just written. There is an asymmetry between the two
used stream buffers: If writing to the first character fails, it is not
even attempted to write to the second stream buffer. This can be changed
but is rarely a problem because write error are rare anyway (that is, if
there is a problem it becomes a huge problem...). There is a similar
asymmetry for the 'sync()' function. The purpose of this function is to
flush buffers. Since the 'teebuf' does not have a buffer, this request
is just forwarded to the two underlying stream buffers.

Here is a sample use of this stream buffer:

#include "teebuf.h"
#include <iostream>
#include <fstream>
int main() {
std::streambuf* cout_sbuf = std::cout.rdbuf();
std::ofstream fout("file.txt");
teebuf teeout(std::cout.rdbuf(), fout.rdbuf());
std::cout.rdbuf(&teeout);
std::cout << "hello, world\n";
std::cout.rdbuf(cout_sbuf);
}

This program should write "hello, world\n" to both 'std::cout' and the
file "file.txt".

PS: It took me about 25 minuts to answer the question...
--
<mailto:dietma...@claas-solutions.de>
homepage: <http://www.informatik.uni-konstanz.de/~kuehl>


Sent via Deja.com http://www.deja.com/
Before you buy.

Alex Vinokur

unread,
Oct 13, 1999, 3:00:00 AM10/13/99
to
In article <19991012134236...@ng-fz1.aol.com>,
dremt...@aol.com (DREMTIME98) wrote:
[snip]

>
> Now to my question. I wonder how I might be able to direct cout to
not only
> print to the screen but also write to a file. How do you use
redirection for
> that?
>
> Thanks a lot
> Jim.
>
>

Hi,

See below.
Hope this helps.

Alex


//#########################################################
// File#1 of 3 : echo_file.H
//------------------- C++ code : BEGIN -------------------

//###########
// echo_file.H
//###########

#ifndef echo_file_H
#define echo_file_H

#include <string>
#include <iostream.h>
#include <fstream.h>
#include <assert.h>


#define DEFAULT_OutFileName "Default.out"

class echo_file
{

private:
ofstream OutFile;

public:
echo_file ()
{
assert (!OutFile.is_open ());
OutFile.open(DEFAULT_OutFileName);
if (!OutFile.is_open ())
{
cout << "Cannot open "
<< DEFAULT_OutFileName
<< endl;
exit (1);
}
}

void setFileName (char const * const fn)
{
OutFile.close ();
assert (!OutFile.is_open ());
OutFile.open(fn);
if (!OutFile.is_open ())
{
cout << "Cannot open "
<< fn
<< endl;
exit (1);
}
};

~echo_file()
{
OutFile.close();
assert (!OutFile.is_open ());
};

echo_file& operator<< (ostream& v (ostream&))
{
cout << v;
OutFile << v;
return *this;
}

template <class T> echo_file& operator<< (const T& v)
{
cout << v;
OutFile << v;
return *this;
}

};

extern echo_file tout;

#endif

//---------------------------------------------------------
// File#1 of 3 : echo_file.H
//------------------- C++ code : END ----------------------


//#########################################################
// File#2 of 3 : echo_file.C
//------------------- C++ code : BEGIN -------------------

#include "echo_file.H"
echo_file tout;

//---------------------------------------------------------
// File#2 of 3 : echo_file.C
//------------------- C++ code : END ----------------------

//#########################################################
// File#3 of 3 : echo_main.C
//------------------- C++ code : BEGIN -------------------


//###########
// echo_main.C
//###########

#include "echo_file.H"
int main()
{
string s1 = "AAAAA";
char* s2 = "BBBBB";
int i1 = 111;

tout << s1 << endl;
tout << s2 << endl;
tout << "CCCCC" << endl;
tout << i1 << endl;
tout << 222 << endl;

tout.setFileName ("AAA.out");

tout << "HELLO" << endl;
tout << 33333 << endl;

return 0;
}


//---------------------------------------------------------
// File#3 of 3 : echo_main.C
//------------------- C++ code : END ----------------------

//#########################################################
//------------------- Running Results : BEGIN -------------

// Screen
AAAAA
BBBBB
CCCCC
111
222
HELLO
33333


// OutFile : Default.out
AAAAA
BBBBB
CCCCC
111
222


// OutFile : AAA.out
HELLO
33333


//------------------- Running Results : END ---------------

//#########################################################
//------------------- Compiler & System ------------------

g++ -v : gcc version egcs-2.91.57 19980901
(egcs-1.1 release)

uname -sr : SunOS 5.6

//---------------------------------------------------------

//#########################################################

Dietmar Kuehl

unread,
Oct 13, 1999, 3:00:00 AM10/13/99
to
Hi,
In article <7u2275$mbp$1...@nnrp1.deja.com>,
Alex Vinokur <alexande...@telrad.co.il> wrote:
> Hope this helps.

Actually, it does not: It points into the false direction, towards lots
of trouble. You should not fiddle with overloading 'operator<< ()' to
write to a special destination. In the context of streams, this operator
is overloaded to format user defined types. To write to a special
destination like eg. simultaneously to two streams a new stream buffer
is created. See my other answer in this thread for details.

Will H. Stewart

unread,
Oct 13, 1999, 3:00:00 AM10/13/99
to
This is awesome but could you answer my 2 questions? Scan below.
Thanks, Will

Alex Vinokur wrote:
>
> In article <19991012134236...@ng-fz1.aol.com>,
> dremt...@aol.com (DREMTIME98) wrote:
> [snip]
> >
> > Now to my question. I wonder how I might be able to direct cout to
> not only
> > print to the screen but also write to a file. How do you use
> redirection for
> > that?
> >
> > Thanks a lot
> > Jim.
> >

> >******/* Could you please make comments here concerning what this is actually doing. Is it saying when OutFile is not open?*/


>
> Hi,
>
> See below.
> Hope this helps.
>
> Alex
>
> //#########################################################
> // File#1 of 3 : echo_file.H
> //------------------- C++ code : BEGIN -------------------
>
> //###########
> // echo_file.H
> //###########
>
> #ifndef echo_file_H
> #define echo_file_H
>
> #include <string>
> #include <iostream.h>
> #include <fstream.h>
> #include <assert.h>
>
> #define DEFAULT_OutFileName "Default.out"
>
> class echo_file
> {
>
> private:
> ofstream OutFile;
>
> public:
> echo_file ()
> {
> assert (!OutFile.is_open ());

******/* Could you please make comments here concerning what this is
actually doing. Is it saying when OutFile is not open?*/


> OutFile.open(DEFAULT_OutFileName);
> if (!OutFile.is_open ())
> {
> cout << "Cannot open "
> << DEFAULT_OutFileName
> << endl;
> exit (1);
> }
> }
>

> void setFileName (char const * const fn) // Is this * supposed to be a // pointer?????//

Alex Vinokur

unread,
Oct 14, 1999, 3:00:00 AM10/14/99
to
In article <3804A791...@home.com>,

"Will H. Stewart" <international...@home.com> wrote:

> This is awesome but could you answer my 2 questions? Scan below.
> Thanks, Will
>

[snip]

> > //#########################################################
> > // File#1 of 3 : echo_file.H
> > //------------------- C++ code : BEGIN -------------------
> >
> > //###########
> > // echo_file.H
> > //###########
> >
> > #ifndef echo_file_H
> > #define echo_file_H
> >
> > #include <string>
> > #include <iostream.h>
> > #include <fstream.h>
> > #include <assert.h>
> >
> > #define DEFAULT_OutFileName "Default.out"
> >
> > class echo_file
> > {
> >
> > private:
> > ofstream OutFile;
> >
> > public:
> > echo_file ()
> > {

//===============================================
// For instance, if we add the following line

OutFile.open(DEFAULT_OutFileName);

// (i.e. we create erroneous situation in the program,
// because we open this file below),
//===============================================

> > assert (!OutFile.is_open ()); // Line#31


> ******/* Could you please make comments here concerning what this is
> actually doing. Is it saying when OutFile is not open?*/
>

//===============================================
// we will get the following result of the running
// echo_file.H:31: failed assertion `!OutFile.is_open ()'
// Abort (core dumped)

// If OutFile is not open, the assert command is silent.
//===============================================

> > OutFile.open(DEFAULT_OutFileName);
> > if (!OutFile.is_open ())
> > {
> > cout << "Cannot open "
> > << DEFAULT_OutFileName
> > << endl;
> > exit (1);
> > }
> > }
> >
> > void setFileName (char const * const fn) // Is
this * supposed to be a // pointer?????//

//===============================================
// * is pointer.

// Concerning char const * const // see the thread titled "const char*
const" // ------------------ // in comp.lang.c++ // started 1999/02/08
//
http://www.deja.com/=dnc/[ST_rn=ps]/viewthread.xp?search=thread&recnum=%3c79m
ice$oid$1...@nnrp1.dejanews.com%3e%231/1&AN=441840331&svcclass=dnserver&frpage=g
etdoc.xp // ------------------ // in comp.lang.c++.moderated // started
1999/02/08 //
http://www.deja.com/=dnc/[ST_rn=ps]/viewthread.xp?search=thread&recnum=%3c79m
61o$ema$1...@nnrp1.dejanews.com%3e%231/1&AN=442245779&svcclass=dnserver&frpage=g
etdoc.xp //===============================================


> > {
> > OutFile.close ();
> > assert (!OutFile.is_open ());
> > OutFile.open(fn);
> > if (!OutFile.is_open ())
> > {
> > cout << "Cannot open "
> > << fn
> > << endl;
> > exit (1);
> > }
> > };

[snip]

Alex

0 new messages