187

How can I redirect cin to in.txt and cout to out.txt?

Fantastic Mr Fox
  • 32,495
  • 27
  • 95
  • 175
updogliu
  • 6,066
  • 7
  • 37
  • 50
  • 8
    Redirect cin to a string : http://stackoverflow.com/questions/4925150/redirect-cin-to-a-string - Redirect cout to a string : http://stackoverflow.com/questions/1162068/redirect-both-cout-and-stdout-to-a-string-in-c-for-unit-testing – Dr.Kameleon Apr 14 '12 at 02:23

8 Answers8

274

Here is an working example of what you want to do. Read the comments to know what each line in the code does. I've tested it on my pc with gcc 4.6.1; it works fine.

#include <iostream>
#include <fstream>
#include <string>

void f()
{
    std::string line;
    while(std::getline(std::cin, line))  //input from the file in.txt
    {
        std::cout << line << "\n";   //output to the file out.txt
    }
}
int main()
{
    std::ifstream in("in.txt");
    std::streambuf *cinbuf = std::cin.rdbuf(); //save old buf
    std::cin.rdbuf(in.rdbuf()); //redirect std::cin to in.txt!
    
    std::ofstream out("out.txt");
    std::streambuf *coutbuf = std::cout.rdbuf(); //save old buf
    std::cout.rdbuf(out.rdbuf()); //redirect std::cout to out.txt!

    std::string word;
    std::cin >> word;           //input from the file in.txt
    std::cout << word << "  ";  //output to the file out.txt
    
    f(); //call function


    std::cin.rdbuf(cinbuf);   //reset to standard input again
    std::cout.rdbuf(coutbuf); //reset to standard output again

    std::cin >> word;   //input from the standard input
    std::cout << word;  //output to the standard input
}

You could save and redirect in just one line as:

auto cinbuf = std::cin.rdbuf(in.rdbuf()); //save and redirect

Here std::cin.rdbuf(in.rdbuf()) sets std::cin's buffer to in.rdbuf() and then returns the old buffer associated with std::cin. The very same can be done with std::cout — or any stream for that matter.

starball
  • 20,030
  • 7
  • 43
  • 238
Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • 5
    Do I need to close the files before I reset cin and cout to standard IO? – updogliu Apr 15 '12 at 07:10
  • 4
    @updogliu: No. If you want, you can use `in` and `out` to read from and write to, `in.txt` and `out.txt` respectively. Also, the files will be closed automatically when `in` and `out` go out of scope. – Nawaz Apr 15 '12 at 08:44
  • 1
    I like this solution over the `freopen` one because I can no longer get my `stdout` back if I use `freopen`. https://stackoverflow.com/questions/26699524/how-to-write-in-stdout-after-using-freopen – xxks-kkk Oct 20 '18 at 05:30
  • What if I don't want to keep the old buf from cin or cout around? Should I `delete` them? – Kai Petzke Feb 17 '22 at 20:30
  • I tried this solution but i got: **** stack smashing detected *** Is it an expected result in certain cases? – Yaniv G Dec 13 '22 at 08:25
  • @YanivG: What else are you doing apart from what this solution suggests? I'm sure you're doing more stuffs that I did here. Could you post a minimal code that reproduces the error, a screen of the error you're getting. Create gist on Github and share the link here. – Nawaz Dec 13 '22 at 13:04
  • @Nawaz: Thanks, indeed it was my fault. However, I realized that all printouts from the very same thread, where I executed the "cout redirection" go to a file. But all "cout" from another threads, do not go to the file, but they are still silenced and don't show on screen. I wished that redirecting "cout" will effect all running thread. Is this even possible? – Yaniv G Dec 13 '22 at 18:24
  • It should affect all threads. Maybe something is still missing in your code. BTW, did you try doing the redirect-setup BEFORE creating other threads? Try that and see if that works. – Nawaz Dec 13 '22 at 19:49
110

Just write

#include <cstdio>
#include <iostream>
using namespace std;

int main()
{
    freopen("output.txt","w",stdout);
    cout<<"write in file";
    return 0;
}
Tsotne Tabidze
  • 1,278
  • 1
  • 9
  • 9
  • 6
    This will redirect printf too, which in some cases may be a good thing. – JDiMatteo Feb 25 '15 at 22:27
  • 1
    @updogliu as far as my knowledge goes, stdout and cout are in sync all the time – DollarAkshay Mar 05 '16 at 11:46
  • 7
    @AkshayLAradhya Not when you set [`std::sync_with_studio(false);`](http://en.cppreference.com/w/cpp/io/ios_base/sync_with_stdio), although by default it is set to `true`. – vsoftco Oct 28 '16 at 04:01
  • @reggaeguitar This is a little bit ugly solution. You should use std for iostream not stdio. – Přemysl Šťastný Mar 30 '17 at 18:12
  • 2
    @PřemyslŠťastný why? – reggaeguitar Apr 03 '17 at 18:40
  • 1
    @reggaeguitar The C++ standard doesn't require the iostream library to use stdio, so this is not portable. The only reason this answer appears simpler is because the original answer provides more information, and an example of setting and preserving it. – nevelis Jul 19 '17 at 03:01
  • 4
    If the answers were equal in functionality, the C++ equivalent of this would be `ofstream out("out.txt"); cout.rdbuf(out.rdbuf());` - only one extra line, and it's portable. Not soooo much simpler :) – nevelis Jul 19 '17 at 03:03
  • 2
    @nevelis Fair enough, you're right. I guess it depends on whether you need it to be portable or not. The reason I was looking this up was for testing coding challenge problems so I just wanted a quick and easy answer. Obviously that's a very different need than someone writing production code. – reggaeguitar Jul 20 '17 at 17:49
31

Here is a short code snippet for shadowing cin/cout useful for programming contests:

#include <bits/stdc++.h>

using namespace std;

int main() {
    ifstream cin("input.txt");
    ofstream cout("output.txt");

    int a, b;   
    cin >> a >> b;
    cout << a + b << endl;
}

This gives additional benefit that plain fstreams are faster than synced stdio streams. But this works only for the scope of single function.

Global cin/cout redirect can be written as:

#include <bits/stdc++.h>

using namespace std;

void func() {
    int a, b;
    std::cin >> a >> b;
    std::cout << a + b << endl;
}

int main() {
    ifstream cin("input.txt");
    ofstream cout("output.txt");

    // optional performance optimizations    
    ios_base::sync_with_stdio(false);
    std::cin.tie(0);

    std::cin.rdbuf(cin.rdbuf());
    std::cout.rdbuf(cout.rdbuf());

    func();
}

Note that ios_base::sync_with_stdio also resets std::cin.rdbuf. So the order matters.

See also Significance of ios_base::sync_with_stdio(false); cin.tie(NULL);

Std io streams can also be easily shadowed for the scope of single file, which is useful for competitive programming:

#include <bits/stdc++.h>

using std::endl;

std::ifstream cin("input.txt");
std::ofstream cout("output.txt");

int a, b;

void read() {
    cin >> a >> b;
}

void write() {
    cout << a + b << endl;
}

int main() {
    read();
    write();
}

But in this case we have to pick std declarations one by one and avoid using namespace std; as it would give ambiguity error:

error: reference to 'cin' is ambiguous
     cin >> a >> b;
     ^
note: candidates are: 
std::ifstream cin
    ifstream cin("input.txt");
             ^
    In file test.cpp
std::istream std::cin
    extern istream cin;  /// Linked to standard input
                   ^

See also How do you properly use namespaces in C++?, Why is "using namespace std" considered bad practice? and How to resolve a name collision between a C++ namespace and a global function?

Vadzim
  • 24,954
  • 11
  • 143
  • 151
14

assuming your compiles prog name is x.exe and $ is the system shell or prompt

$ x <infile >outfile 

will take input from infile and will output to outfile .

Ahmed Eid
  • 4,414
  • 3
  • 28
  • 34
  • 2
    That is not C++ related and fails in any non-trivial example, for example when your program spawns child processes that write to the console. At least that's the problem I've encountered when I tried such redirection, hence why I'm here. – ashrasmun Mar 22 '19 at 05:23
10

Try this to redirect cout to file.

#include <iostream>
#include <fstream>

int main()
{
    /** backup cout buffer and redirect to out.txt **/
    std::ofstream out("out.txt");

    auto *coutbuf = std::cout.rdbuf();
    std::cout.rdbuf(out.rdbuf());

    std::cout << "This will be redirected to file out.txt" << std::endl;

    /** reset cout buffer **/
    std::cout.rdbuf(coutbuf);

    std::cout << "This will be printed on console" << std::endl;

    return 0;
}

Read full article Use std::rdbuf to Redirect cin and cout

Haseeb Mir
  • 928
  • 1
  • 13
  • 22
  • 4
    The question had been answered almost 6 years back (in 2012), yet you've added an answer now in 2018. Your answer is same as the accepted answer. So I'm wondering why did you post this when you didn't have *anything* **new** to add? – Nawaz Jun 19 '18 at 07:57
  • 1
    My answer highlight only cout version specially and the detailed answer is provided in the link below. – Haseeb Mir Jun 21 '18 at 06:20
  • 3
    What is *new* in your answer which is not present in the *accepted* answer? – Nawaz Jun 21 '18 at 08:31
  • 4
    My answer doesn’t mix redirection of both cout and cin , my version separates to make it more readable – Haseeb Mir Jun 21 '18 at 12:45
  • @HaseeBMir But the question was how to redirect `cin` AND `cout`. And sorry, most programmers will be able to strip that half of the accepted answer, that they don't need, if they redirect only `cin` or only `cout`. – Kai Petzke Feb 17 '22 at 20:34
  • 1
    This answer added the new piece of info for how to reset cout to the normal situation. Very useful, very readable, and includes a reference link. Thanks Haseeb. +1 – Roland Mar 06 '23 at 18:45
2

If your input file is in.txt, you can use freopen to set stdin file as in.txt

freopen("in.txt","r",stdin);

if you want to do the same with your output:

freopen("out.txt","w",stdout);

this will work for std::cin (if using c++), printf, etc...

This will also help you in debugging your code in clion, vscode

Edit
If you want to reset stdin

fclose(stdin);
stdin = fdopen(0, "r"); //reopen: 0 is file descriptor of std input

and to reset stdout

fclose(stdout);
stdout = fdopen(1, "w"); //reopen: 1 is file descriptor of std output
Vishal Singh
  • 1,341
  • 14
  • 13
1

I/O Redirection in C++

https://www.geeksforgeeks.org/io-redirection-c/

// Cpp program to redirect cout to a file
#include <fstream>
#include <iostream>
#include <string>
 
using namespace std;
 
int main()
{
    fstream file;
    file.open("cout.txt", ios::out);
    string line;
 
    // Backup streambuffers of  cout
    streambuf* stream_buffer_cout = cout.rdbuf();
    streambuf* stream_buffer_cin = cin.rdbuf();
 
    // Get the streambuffer of the file
    streambuf* stream_buffer_file = file.rdbuf();
 
    // Redirect cout to file
    cout.rdbuf(stream_buffer_file);
 
    cout << "This line written to file" << endl;
 
    // Redirect cout back to screen
    cout.rdbuf(stream_buffer_cout);
    cout << "This line is written to screen" << endl;
 
    file.close();
    return 0;
}
  • 1
    Hello and welcome to Stackoverflow. You have answered a very old question with many answers. Please [edit](https://stackoverflow.com/posts/67770129/edit) your question and add an explanation why this answer is better than the others – Michael Kotzjan May 31 '21 at 09:42
1

The accepted answer shows the right way to redirect cin and cout. You need to construct another stream object whose life time exceeds that of cin or cout. If you want to write a function works like freopen, you can alloc an array for each stream to be redirected, to save the allocated stream objects.

#include <iostream>
#include <string>
#include <fstream>
#include <vector>

using namespace std;

template<typename>
    struct fstream_traits { };
template<typename CharT, typename Traits>
    struct fstream_traits<basic_istream<CharT, Traits>> { using type = basic_ifstream<CharT, Traits>; };
template<typename CharT, typename Traits>
    struct fstream_traits<basic_ostream<CharT, Traits>> { using type = basic_ofstream<CharT, Traits>; };

template <typename Stream>
void redirect(Stream& str, string filename)
{
    using fstream_type = typename fstream_traits<Stream>::type;
    static int index = std::ios_base::xalloc();
    if (str.pword(index) == nullptr)
    {
        str.pword(index)= new vector<ios_base*>{};
        str.register_callback([](ios_base::event event, std::ios_base& stream, int index) {
            if (event == ios_base::erase_event)
            {
                for (auto fs : *(vector<ios_base*>*)stream.pword(index))
                    delete fs;
                delete (vector<ios_base*>*)stream.pword(index);
            }
        }, index);
    }
    vector<ios_base*>* list = (vector<ios_base*>*)str.pword(index);
    list->push_back(new fstream_type{filename});
    str.rdbuf(dynamic_cast<fstream_type*>(list->back())->rdbuf())->~basic_streambuf();
}

int main()
{
    redirect(cout, "out.txt");
    cout << "Redirected text!";
    return 0;
}

The template and alias are not required if you explicitly use istream/ostream instead of Stream.

Tuff Contender
  • 259
  • 4
  • 11