GESP Level 4 – (2) C++ File Redirection and File Read/Write Operations

1. File Read/Write

C++ provides two main methods for file read/write operations: the C-style FILE* method and the C++ stream-based fstream method.

1) FILE File Pointer

<span>FILE</span> is a structure type defined in <stdio.h>, which includes information such as file descriptor, buffer information, current read/write position, and error and end-of-file flags.

Common Modes:

  • <span>"r"</span> – Read-only (file must exist)
  • <span>"w"</span> – Write-only (create new file or clear existing file)
  • <span>"a"</span> – Append (write at the end of the file)
  • <span>"r+"</span> – Read/Write (file must exist)
  • <span>"w+"</span> – Read/Write (create new file or clear existing file)
  • <span>"a+"</span> – Read/Write (start from the end of the file)
  • Add <span>"b"</span> to the mode string, e.g., <span>"rb"</span>, <span>"wb+"</span>
//1. Open file FILE *fopen(const char *filename, const char *mode); //2. Close file int fclose(FILE *stream);//3. Formatted input/output int fprintf(FILE *stream, const char *format, ...); int fscanf(FILE *stream, const char *format, ...);//4. Character input/output int fgetc(FILE *stream); int fputc(int c, FILE *stream);//5. Line input/output char *fgets(char *str, int n, FILE *stream); int fputs(const char *str, FILE *stream);//6. Binary read/write size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);//7. File positioning int fseek(FILE *stream, long offset, int whence); long ftell(FILE *stream); void rewind(FILE *stream);//8. Error handling int feof(FILE *stream);  // Check end-of-file flag int ferror(FILE *stream); // Check error flag void clearerr(FILE *stream); // Clear error flag//9. Buffer control int fflush(FILE *stream); // Force flush buffer void setbuf(FILE *stream, char *buf); // Set buffer int setvbuf(FILE *stream, char *buf, int mode, size_t size); // More fine control 

Comprehensive example is as follows:

#include &lt;stdio.h&gt;#include &lt;stdlib.h&gt;int main() {    // Write to file    FILE *fp = fopen("example.dat", "w+");    if (!fp) {        perror("File opening failed");        return EXIT_FAILURE;    }    fprintf(fp, "Text data: %d\n", 42);    fputs("Another line\n", fp);
    // Binary write    double data[] = {1.1, 2.2, 3.3};    fwrite(data, sizeof(double), 3, fp);
    // Go back to the beginning of the file    rewind(fp);
    // Read text    char buffer[100];    while (fgets(buffer, sizeof(buffer), fp)) {        printf("%s", buffer);    }
    // Check if end of file is reached    if (feof(fp)) {        printf("End of file reached.\n");    }
    fclose(fp);    return 0;}

2) fstream

<span>fstream</span> is a stream class in the C++ standard library used for file input/output, providing an object-oriented interface for file operations, which is safer and more aligned with C++ programming style than the C-style <span>FILE*</span> method. It mainly has two commonly used classes:

  • <span>ifstream</span> – for file input (reading)
  • <span>ofstream</span> – for file output (writing)
  • <span>fstream</span> – for bidirectional file operations (read/write)

Open File

First method: Constructor

std::ifstream inFile("input.txt");  // Open for read only std::ofstream outFile("output.txt"); // Open for write only std::fstream ioFile("data.txt", std::ios::in | std::ios::out); // Open for read/write

Second method: open method

std::fstream file; file.open("example.txt", std::ios::out | std::ios::app);

Common file opening modes can be combined

Mode Flag Description
std::ios::in Read
std::ios::out Write
std::ios::app Append
std::ios::ate Position at the end of the file when opened
std::ios::trunc If the file exists, clear it
std::ios::binary Binary mode

Check File Status

if (file.is_open()) { /* File opened successfully */ } if (file.fail()) { /* Operation failed */ } if (file.eof()) { /* Reached end of file */ } if (file.good()) { /* All good */ }

Complete Example

#include &lt;fstream&gt;#include &lt;iostream&gt;#include &lt;vector&gt;int main() {    // Write binary data    {        std::ofstream out("data.bin", std::ios::binary);        if (!out) {            std::cerr &lt;&lt; "Cannot open file for writing!" &lt;&lt; std::endl;            return 1;        }
        std::vector&lt;int&gt; data = {1, 2, 3, 4, 5};        out.write(reinterpret_cast&lt;const char*&gt;(data.data()),                   data.size() * sizeof(int));    } // out goes out of scope, automatically closes    // Read binary data    {        std::ifstream in("data.bin", std::ios::binary);        if (!in) {            std::cerr &lt;&lt; "Cannot open file for reading!" &lt;&lt; std::endl;            return 1;        }
        // Get file size        in.seekg(0, std::ios::end);        size_t size = in.tellg();        in.seekg(0, std::ios::beg);
        std::vector&lt;int&gt; data(size / sizeof(int));        in.read(reinterpret_cast&lt;char*&gt;(data.data()), size);
        for (int n : data) {            std::cout &lt;&lt; n &lt;&lt; " ";        }        std::cout &lt;&lt; std::endl;    }    return 0;}

2. File Redirection

File redirection refers to the process of changing the program’s standard input/output streams (stdin/stdout/stderr) to other files or devices. In C++, file redirection can be achieved in various ways.

1) freopen

freopen is a file operation function in the C standard library used to reopen an existing file stream (such as stdin, stdout, stderr) and redirect it to another file or device. It is also available in C++.

#include &lt;cstdio&gt;int main() {    // Redirect standard output to a file    if (freopen("output.txt", "w", stdout) == NULL) {        perror("Failed to redirect stdout");        return 1;    }
    printf("This will be written to the output.txt file\n");
    // Restore standard output to console    // Linux/macOS:    freopen("/dev/tty", "w", stdout);    // Windows:    // freopen("CON", "w", stdout);
    printf("This will be displayed on the console\n");
    return 0;}

2) rdbuf()

rdbuf() is a core function in the C++ standard library used to manipulate stream buffers, providing direct access and control over stream buffers, which is a key mechanism for implementing stream redirection. It is the low-level abstraction of the C++ I/O system, responsible for actual data read/write operations, with each stream object (such as cout, ifstream) associated with a streambuf.

// Get current stream buffer std::streambuf* old_buffer = stream.rdbuf();// Set new stream buffer and return old std::streambuf* old_buffer = stream.rdbuf(new_buffer);

Specific example is as follows:

#include &lt;iostream&gt;#include &lt;fstream&gt;int main() {    // Save original cout buffer    std::streambuf* orig_buf = std::cout.rdbuf();    // Redirect to file    std::ofstream out("output.txt");    std::cout.rdbuf(out.rdbuf());    std::cout &lt;&lt; "This line will be written to output.txt file\n";    std::cout &lt;&lt; 42 &lt;&lt; " " &lt;&lt; 3.14 &lt;&lt; std::endl;
    // Restore standard output    std::cout.rdbuf(orig_buf);    std::cout &lt;&lt; "This line will be displayed on the console\n";
    return 0;}

Leave a Comment