Writing to both terminal and file c++
Asked Answered
C

4

6

I found this question answered for Python, Java, Linux script, but not C++:

I'd like to write all outputs of my C++ program to both the terminal and an output file. Using something like this:

int main ()
{
freopen ("myfile.txt","w",stdout);
cout<< "Let's try this"; 
fclose (stdout);
return 0;
}

outputs it to only the output file named "myfile.txt", and prevents it from showing on the terminal. How can I make it output to both simultaneously? I use visual studio 2010 express (if that would make any difference).

Thanks in advance!

Chuvash answered 20/1, 2014 at 11:13 Comment(2)
You use a different stream object, one which duplicates the calls to a file and to stdoutBoult
possible duplicate of Custom C++ cout class - output to both console and log filePuryear
N
8

Possible solution: use a static stream cout-like object to write both to cout and a file.

Rough example:

struct LogStream 
{
    template<typename T> LogStream& operator<<(const T& mValue)
    {
        std::cout << mValue;
        someLogStream << mValue;
    }
};

inline LogStream& lo() { static LogStream l; return l; }

int main()
{
    lo() << "hello!";
    return 0;
}

You will probably need to explicitly handle stream manipulators, though.

Here is my library implementation.

Neoteny answered 20/1, 2014 at 11:18 Comment(1)
@Aly: if you are satisfied, do you mind accepting this answer so that the question can be marked as "solved"? Thanks. Alternatively, you can post your own answer and accept it.Neoteny
T
1

There is no built in way to do this in one step. You have to write the data to a file and then write the data out on screen in two steps.

You can write a function that takes in the data and the filename and does this for you, to save you time, some sort of logging function.

Tol answered 20/1, 2014 at 11:17 Comment(0)
N
1

I have a method to do this, and it is based on a subscriber model.

In this model all your logging goes to a "logging" manager and you then have "subscribers" that decide what to do with the messages. Messages have topics (for me a number) and loggers subscribe to one or more topic.

For your purpose, you create 2 subscribers, one that outputs to the file and one that outputs to the console.

In the logic of your code you simply output the message, and at this level not need to know what is going to be done with it. In my model though you can check first if there are any "listeners" as this is considered cheaper than constructing and outputting messages that will only end up in /dev/null (well you know what I mean).

Neddie answered 20/1, 2014 at 11:21 Comment(1)
Upvoted because it's a good answer; however, it may be too heavy-weight for what the OP wants.Kati
P
0

One way to do this would be to write a small wrapper to do this, for example:

class DoubleOutput
{
public:
  // Open the file in the constructor or any other method
  DoubleOutput(const std::string &filename);   
  // ...
  // Write to both the file and the stream here
  template <typename T>
  friend DoubleOutput & operator<<(const T& file);
// ...
private:
  FILE *file;
}

To have a class instead of a function makes you use the RAII idiom (https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization)

To use it:

DoubleOutput mystream("myfile");
mystream << "Hello World";
Pool answered 20/1, 2014 at 11:21 Comment(1)
I think you need to extend the answer a bit. It does not work in current form.Garcia

© 2022 - 2024 — McMap. All rights reserved.