简体   繁体   中英

Writing to both terminal and file c++

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!

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.

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.

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).

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";

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM