Redirección de E/S en C++

En C, podríamos usar la función freopen() para redirigir un puntero de ARCHIVO existente a otra secuencia. El prototipo de freopen() se da como 

FILE * freopen ( const char * filename, const char * mode, FILE * stream );

Por ejemplo, para redirigir la salida estándar para decir un archivo de texto, podríamos escribir:

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

Si bien este método todavía se admite en C++, este artículo analiza otra forma de redirigir flujos de E/S.
C++, al ser un lenguaje de programación orientado a objetos, nos brinda la capacidad no solo de definir nuestros propios flujos, sino también de redirigir flujos estándar. Así, en C++, un flujo es un objeto cuyo comportamiento está definido por una clase. Por lo tanto, cualquier cosa que se comporte como un flujo también es un flujo. 
Los objetos Streams en C++ son principalmente de tres tipos: 
 

  • istream: el objeto de flujo de este tipo solo puede realizar operaciones de entrada desde el flujo
  • ostream: estos objetos solo se pueden usar para operaciones de salida.
  • iostream: se puede utilizar tanto para operaciones de entrada como de salida

Todas estas clases, así como las clases de flujo de archivos, derivadas de las clases: ios y streambuf. Por lo tanto, los objetos filestream y IO stream se comportan de manera similar.
Todos los objetos de flujo también tienen un miembro de datos asociado de la clase streambuf. En pocas palabras, el objeto streambuf es el búfer para la transmisión. Cuando leemos datos de una transmisión, no los leemos directamente de la fuente, sino que los leemos del búfer que está vinculado a la fuente. De manera similar, las operaciones de salida se realizan primero en el búfer y luego el búfer se vacía (se escribe en el dispositivo físico) cuando es necesario.
C++ nos permite configurar el búfer de flujo para cualquier flujo, por lo que la tarea de redirigir el flujo simplemente se reduce a cambiar el búfer de flujo asociado con el flujo. Por lo tanto, para redirigir una secuencia A a una secuencia B, debemos hacer lo siguiente:
 

  1. Obtenga el búfer de transmisión de A y guárdelo en algún lugar
  2. Establezca el búfer de transmisión de A en el búfer de transmisión de B
  3. Si es necesario restablecer el búfer de transmisión de A a su búfer de transmisión anterior

Podemos usar la función ios::rdbuf() para realizar las siguientes dos operaciones. 

1) stream_object.rdbuf(): Returns pointer to the stream buffer of stream_object
2) stream_object.rdbuf(streambuf * p): Sets the stream buffer to the object pointed by p

Aquí hay un programa de ejemplo a continuación para mostrar los pasos 

CPP

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

Producción: 

This line is written to screen
Contents of file cout.txt:
This line written to file

Complejidad de tiempo: O(1)

Complejidad espacial: O(1)

Nota: 
Los pasos anteriores se pueden condensar en un solo paso 

auto cout_buf = cout.rdbuf(file.rdbuf())

// sets couts streambuffer and returns the old 
streambuffer back to cout_buf

Referencias: 
CPP IOS
 

Publicación traducida automáticamente

Artículo escrito por Sayan Mahapatra y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *