Страницы

Поиск по вопросам

четверг, 19 декабря 2019 г.

Можно ли связать файловый поток с потоком cout?

#cpp #cpp11 #filestream


Я рассчитывал на то, что cout будет выводить всё, что было записано в файловый поток,
но этого не происходит.

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

    


Ответы

Ответ 1



std::basic_ios::tie это не про это и то, чего Вы хотите добиться реализуется не так просто. Точнее, для этого нет встроенных средств, которые можно использовать не добавляя кода. То, что Вы хотите можно реализовать следующий образом: делаем свой буфер, который можно связывать с несколькими буферами, потом свой поток данных, который будет использовать этой буфер. Выглядеть это может так: 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 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; }; И использовать это можно так: Multistream multi; multi.tie(out); multi.tie(std::cout); multi << "Hello World!" << endl; out.close(); Только учтите, что это слишком базовая реализация буфера, в которой нет проверок на eof и прочих. Но его можно доработать под Ваши нужды.

Ответ 2



Лучше так не делать. Нужно STDOUT перенаправить в файл, запусти программу как program_name > hello_world.txt Но если очень нужно, например для демона, то: открой файл при помощи ::open() - не стоит использовать ::fopen(), так как появится головная боль с буферами и их соглосованием. сделай дупликацию дескрипторов при помощи dup2() ... PROFIT! если точнее, то просто продолжаешь пользовать std::cout как и раньше, но текст будет попадать в файл. Закрывать уже нужно будет сам файловый дескриптор. Вот пример: #include #include #include #include #include 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; } Аналогично можно сделать для STDERR_FILENO - стандартный поток ошибок. Он используется std::cerr и std::clog (первый не буфферизированный, второй, как и std::cout - буфферизированный). Для Windows стоит уточнить поведение и где находятся объявления ::open() и dup2() и их альтернативы: dup/dup2 vs _dup/_dup2 open vs _open vs _sopen

Комментариев нет:

Отправить комментарий