I expected that cout will output everything that was written to the file stream, but this does not happen.

 using namespace std; int main(int argc, char *argv[]) { fstream out("hello_world.txt",ofstream::out, ofstream::trunc); out.tie(&cout); out << "Hello World!" << endl; out.close(); return 0; } 

    2 answers 2

    std :: basic_ios :: tie is not about that and what you want to achieve is not so easy to implement. More precisely, there are no built-in tools for this, which can be used without adding code. What you want can be implemented in the following way: we make our own buffer, which can be linked to several buffers, then our data stream, which will use this buffer. It may look like this:

     class Multibuffer: public std::streambuf { public: void tieBuffer(std::streambuf* buffer) { m_Buffers.emplace_back(buffer); } int overflow(int character) override { for(auto& buffer : m_Buffers) buffer->sputc(character); return character; } private: std::vector<std::streambuf*> m_Buffers; }; class Multistream: public std::ostream { public: Multistream(): std::ostream(nullptr) { rdbuf(&m_Buffer); } void tie(std::ostream& stream) { stream.tie(this); m_Buffer.tieBuffer(stream.rdbuf()); } private: Multibuffer m_Buffer; }; 

    And you can use it like this:

     Multistream multi; multi.tie(out); multi.tie(std::cout); multi << "Hello World!" << endl; out.close(); 

    Just eof in eof that this is too basic implementation of the buffer, in which there are no checks on eof and others. But it can be customized for your needs.

      Better not to do that. It is necessary to redirect STDOUT to a file, run the program as

       program_name > hello_world.txt 

      But if you really need, for example for a demon, then:

      1. open the file with ::open() - do not use ::fopen() , as there will be a headache with buffers and their matching.
      2. duplicate descriptors with dup2()
      3. ...
      4. PROFIT!

      more precisely, you simply continue to use std::cout as before, but the text will fall into the file. Already need to close the file descriptor itself.

      Here is an example:

       #include <fcntl.h> #include <unistd.h> #include <cstdlib> #include <cstdint> #include <iostream> using namespace std; int main() { auto fd = ::open("./hello.txt", O_APPEND | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); // Дуплицируем наш дескриптор на стандартный выход dup2(fd, STDOUT_FILENO); // С этого момента, всё, что попадает в std::cout - попадает в файл. cout << "Hello, world!\n"; cout << flush; ::close(fd); return 0; } 

      Similarly, you can do for STDERR_FILENO - the standard error stream. It is used by std::cerr and std::clog (the first is not buffered, the second, like std::cout is buffered).

      For Windows, it is worthwhile to clarify the behavior and where are the ::open() and dup2() declarations and their alternatives:

      • Yes, if the output was initially using std::cout , then do not forget to duplicate buffers before duplicating descriptors. And then a piece of the current one will be written, and then you will think - where is the joint. And it's better to do this before any output to the console. - Monah Tuk
      • Honestly, I would probably write my own method that would output both to a file and to the console ... It is more obvious to support than this. By the way, if redirection is needed, it is not easier to use freopen("output.txt","w",stdout); ? Or did I not understand the question? - pavel
      • No, I read the crooked question. @ixSci gave the correct answer. - Monah Tuk