Perform File Operations in C++

C++C++Beginner
Practice Now

Introduction

In this lab, you will learn how to perform various file operations in C++. The lab covers opening files for reading and writing, writing text data to files, reading data from text files, checking file open status, handling file read/write errors, working with binary files, positioning the file pointer, and closing files to release resources. You will gain practical experience in using the fundamental file stream classes ofstream and ifstream from the C++ standard library to interact with files. By the end of this lab, you will have a solid understanding of file handling in C++ programming.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL cpp(("`C++`")) -.-> cpp/IOandFileHandlingGroup(["`I/O and File Handling`"]) cpp(("`C++`")) -.-> cpp/BasicsGroup(["`Basics`"]) cpp(("`C++`")) -.-> cpp/AdvancedConceptsGroup(["`Advanced Concepts`"]) cpp(("`C++`")) -.-> cpp/ControlFlowGroup(["`Control Flow`"]) cpp(("`C++`")) -.-> cpp/StandardLibraryGroup(["`Standard Library`"]) cpp/IOandFileHandlingGroup -.-> cpp/output("`Output`") cpp/BasicsGroup -.-> cpp/strings("`Strings`") cpp/AdvancedConceptsGroup -.-> cpp/structures("`Structures`") cpp/AdvancedConceptsGroup -.-> cpp/pointers("`Pointers`") cpp/IOandFileHandlingGroup -.-> cpp/files("`Files`") cpp/AdvancedConceptsGroup -.-> cpp/exceptions("`Exceptions`") cpp/ControlFlowGroup -.-> cpp/if_else("`If...Else`") cpp/StandardLibraryGroup -.-> cpp/string_manipulation("`String Manipulation`") subgraph Lab Skills cpp/output -.-> lab-446086{{"`Perform File Operations in C++`"}} cpp/strings -.-> lab-446086{{"`Perform File Operations in C++`"}} cpp/structures -.-> lab-446086{{"`Perform File Operations in C++`"}} cpp/pointers -.-> lab-446086{{"`Perform File Operations in C++`"}} cpp/files -.-> lab-446086{{"`Perform File Operations in C++`"}} cpp/exceptions -.-> lab-446086{{"`Perform File Operations in C++`"}} cpp/if_else -.-> lab-446086{{"`Perform File Operations in C++`"}} cpp/string_manipulation -.-> lab-446086{{"`Perform File Operations in C++`"}} end

Open Files Using ofstream and ifstream

In this step, you'll learn how to open files in C++ using two fundamental file stream classes: ofstream for writing files and ifstream for reading files. These classes are part of the C++ standard library and provide essential file handling capabilities.

First, navigate to the project directory in the WebIDE terminal:

cd ~/project

Create a new C++ file called file_operations.cpp:

touch file_operations.cpp

Add the following code to the file_operations.cpp file:

#include <iostream>
#include <fstream>  // Include file stream header

int main() {
    // Opening a file for writing using ofstream
    std::ofstream outputFile("example.txt");

    // Check if the file is successfully opened
    if (outputFile.is_open()) {
        std::cout << "File opened for writing successfully!" << std::endl;
        outputFile.close();  // Close the file
    } else {
        std::cout << "Unable to open file for writing." << std::endl;
    }

    // Opening a file for reading using ifstream
    std::ifstream inputFile("example.txt");

    // Check if the file is successfully opened
    if (inputFile.is_open()) {
        std::cout << "File opened for reading successfully!" << std::endl;
        inputFile.close();  // Close the file
    } else {
        std::cout << "Unable to open file for reading." << std::endl;
    }

    return 0;
}

Let's break down the key concepts:

  1. #include <fstream>: Includes the file stream library
  2. std::ofstream: Output file stream for writing files
  3. std::ifstream: Input file stream for reading files
  4. is_open(): Checks if the file was successfully opened
  5. close(): Closes the file after operations

Compile the program:

g++ file_operations.cpp -o file_operations

Run the executable:

./file_operations

Example output:

File opened for writing successfully!
File opened for reading successfully!

Some important points about file streams:

  • Always check if a file is successfully opened before performing operations
  • Remember to close files after you're done using them
  • ofstream is used for writing to files
  • ifstream is used for reading from files
  • Both classes are part of the <fstream> header

You can think of file streams like opening and closing doors to files. ofstream lets you write into a room, while ifstream allows you to read what's inside.

Write Text Data to Files

In this step, you'll learn how to write text data to files using the ofstream class in C++. Building on the previous step, you'll explore different ways to write strings, numbers, and multiple lines to files.

Create a new C++ file called write_files.cpp:

touch ~/project/write_files.cpp

Add the following code to the write_files.cpp file:

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

int main() {
    // Open a file for writing
    std::ofstream outputFile("student_data.txt");

    // Check if the file is successfully opened
    if (outputFile.is_open()) {
        // Writing a single string
        outputFile << "John Doe" << std::endl;

        // Writing multiple pieces of data
        std::string name = "Alice Smith";
        int age = 22;
        double gpa = 3.75;
        outputFile << name << ", " << age << " years old, GPA: " << gpa << std::endl;

        // Writing multiple lines
        outputFile << "Computer Science Student" << std::endl;
        outputFile << "University of Programming" << std::endl;

        // Close the file
        outputFile.close();
        std::cout << "Data written to file successfully!" << std::endl;
    } else {
        std::cout << "Unable to open file for writing." << std::endl;
    }

    return 0;
}

Compile the program:

g++ write_files.cpp -o write_files

Run the executable:

./write_files

Example output:

Data written to file successfully!

Verify the file contents:

cat student_data.txt

Example file contents:

John Doe
Alice Smith, 22 years old, GPA: 3.75
Computer Science Student
University of Programming

Key points about writing to files:

  • Use << operator to write data to files
  • std::endl adds a new line
  • Can write strings, numbers, and variables
  • Always check if file is open before writing
  • Close the file after writing operations

You can think of writing to files like writing in a notebook. The ofstream is your pen, and the file is the page where you record information.

Read Data from Text Files

In this step, you'll learn how to read data from text files using the ifstream class in C++. Building on the previous steps, you'll explore different methods to read lines, words, and entire files.

Create a new C++ file called read_files.cpp:

touch ~/project/read_files.cpp

Add the following code to the read_files.cpp file:

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

int main() {
    // Open the file created in the previous step
    std::ifstream inputFile("student_data.txt");

    // Check if the file is successfully opened
    if (inputFile.is_open()) {
        // Read entire line
        std::string line;
        std::cout << "Reading entire lines:" << std::endl;
        while (std::getline(inputFile, line)) {
            std::cout << line << std::endl;
        }

        // Reset file pointer to beginning
        inputFile.clear();
        inputFile.seekg(0, std::ios::beg);

        // Read individual words
        std::cout << "\nReading individual words:" << std::endl;
        std::string word;
        while (inputFile >> word) {
            std::cout << word << " ";
        }
        std::cout << std::endl;

        // Close the file
        inputFile.close();
    } else {
        std::cout << "Unable to open file for reading." << std::endl;
    }

    return 0;
}

Compile the program:

g++ read_files.cpp -o read_files

Run the executable:

./read_files

Example output:

Reading entire lines:
John Doe
Alice Smith, 22 years old, GPA: 3.75
Computer Science Student
University of Programming

Reading individual words:
John Doe Alice Smith, 22 years old, GPA: 3.75 Computer Science Student University of Programming

Key points about reading files:

  • Use std::getline() to read entire lines
  • Use >> operator to read individual words
  • clear() and seekg() reset file pointer
  • Always check if file is open before reading
  • Close the file after reading operations

You can think of reading files like extracting information from a book. The ifstream is your bookmark, helping you navigate through the text.

Check File Open Status

In this step, you'll learn how to check the status of file operations in C++ using various methods to verify if files are successfully opened and ready for reading or writing.

Create a new C++ file called file_status.cpp:

touch ~/project/file_status.cpp

Add the following code to the file_status.cpp file:

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

int main() {
    // Attempt to open an existing file for reading
    std::ifstream inputFile("student_data.txt");

    // Method 1: Using is_open() to check file status
    if (inputFile.is_open()) {
        std::cout << "File opened successfully for reading." << std::endl;

        // Perform reading operations
        std::string line;
        while (std::getline(inputFile, line)) {
            std::cout << "Read line: " << line << std::endl;
        }

        inputFile.close();
    } else {
        std::cout << "Failed to open file for reading." << std::endl;
    }

    // Method 2: Using good() to check file state
    std::ofstream outputFile("test_status.txt");

    if (outputFile.good()) {
        std::cout << "File opened successfully for writing." << std::endl;
        outputFile << "Testing file status" << std::endl;

        // Additional status checks
        if (outputFile) {
            std::cout << "File is in a good state for writing." << std::endl;
        }

        outputFile.close();
    } else {
        std::cout << "Failed to open file for writing." << std::endl;
    }

    // Method 3: Multiple status check methods
    std::ifstream checkFile("non_existent_file.txt");

    std::cout << "File status checks:" << std::endl;
    std::cout << "is_open(): " << (checkFile.is_open() ? "True" : "False") << std::endl;
    std::cout << "good(): " << (checkFile.good() ? "True" : "False") << std::endl;
    std::cout << "fail(): " << (checkFile.fail() ? "True" : "False") << std::endl;

    return 0;
}

Compile the program:

g++ file_status.cpp -o file_status

Run the executable:

./file_status

Example output:

File opened successfully for reading.
Read line: John Doe
Read line: Alice Smith, 22 years old, GPA: 3.75
Read line: Computer Science Student
Read line: University of Programming
File opened successfully for writing.
File is in a good state for writing.
File status checks:
is_open(): False
good(): False
fail(): True

Key points about file status checking:

  • is_open(): Checks if the file was successfully opened
  • good(): Checks if no errors have occurred
  • fail(): Checks if an error has occurred
  • Always check file status before performing operations
  • Different methods provide various ways to verify file state

You can think of file status checks like a safety inspection before a journey. These methods help ensure your file operations are safe and successful.

Handle File Read/Write Errors

In this step, you'll learn how to handle potential errors that can occur during file read and write operations in C++. Understanding error handling is crucial for creating robust file manipulation programs.

Create a new C++ file called file_error_handling.cpp:

touch ~/project/file_error_handling.cpp

Add the following code to the file_error_handling.cpp file:

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

void writeToFile(const std::string& filename) {
    std::ofstream outputFile(filename);

    // Check if file is open
    if (!outputFile) {
        // Throw an exception if file cannot be opened
        throw std::runtime_error("Unable to open file for writing: " + filename);
    }

    try {
        // Attempt to write data
        outputFile << "Hello, Error Handling!" << std::endl;
        outputFile << "This is a sample text." << std::endl;

        // Simulate a write error (intentionally not recommended)
        if (outputFile.bad()) {
            throw std::runtime_error("Write operation failed");
        }
    }
    catch (const std::exception& e) {
        std::cerr << "Error during writing: " << e.what() << std::endl;
    }

    outputFile.close();
}

void readFromFile(const std::string& filename) {
    std::ifstream inputFile(filename);
    std::string line;

    // Check if file is open
    if (!inputFile) {
        // Throw an exception if file cannot be opened
        throw std::runtime_error("Unable to open file for reading: " + filename);
    }

    try {
        // Read and print file contents
        std::cout << "File contents:" << std::endl;
        while (std::getline(inputFile, line)) {
            std::cout << line << std::endl;
        }

        // Check for read errors
        if (inputFile.bad()) {
            throw std::runtime_error("Read operation encountered an error");
        }
    }
    catch (const std::exception& e) {
        std::cerr << "Error during reading: " << e.what() << std::endl;
    }

    inputFile.close();
}

int main() {
    try {
        // Write to a file
        writeToFile("error_handling_example.txt");

        // Read from the file
        readFromFile("error_handling_example.txt");

        // Attempt to read from a non-existent file
        readFromFile("non_existent_file.txt");
    }
    catch (const std::exception& e) {
        std::cerr << "Main error: " << e.what() << std::endl;
        return 1;
    }

    return 0;
}

Compile the program:

g++ file_error_handling.cpp -o file_error_handling

Run the executable:

./file_error_handling

Example output:

File contents:
Hello, Error Handling!
This is a sample text.
Error during reading: Unable to open file for reading: non_existent_file.txt

Key points about file error handling:

  • Use try-catch blocks to handle potential exceptions
  • Check file stream state before and after operations
  • Use std::runtime_error for throwing meaningful error messages
  • Handle different types of file-related errors
  • Provide informative error messages

You can think of error handling like a safety net. It catches potential problems and prevents your program from crashing unexpectedly.

Work with Binary Files Using fstream

In this step, you'll learn how to work with binary files using the fstream class in C++. Binary files store data in its raw binary format, which is different from text files and useful for storing structured data efficiently.

Create a new C++ file called binary_files.cpp:

touch ~/project/binary_files.cpp

Add the following code to the binary_files.cpp file:

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

// Simple struct to demonstrate binary file writing
struct Student {
    int id;
    char name[50];
    double gpa;
};

void writeBinaryFile() {
    std::fstream binaryFile("students.bin", std::ios::out | std::ios::binary);

    if (!binaryFile) {
        std::cerr << "Error opening file for writing!" << std::endl;
        return;
    }

    // Create some student records
    Student students[3] = {
        {1, "John Doe", 3.5},
        {2, "Alice Smith", 3.8},
        {3, "Bob Johnson", 3.2}
    };

    // Write entire struct to binary file
    binaryFile.write(reinterpret_cast<char*>(students), sizeof(students));

    binaryFile.close();
    std::cout << "Binary file written successfully!" << std::endl;
}

void readBinaryFile() {
    std::fstream binaryFile("students.bin", std::ios::in | std::ios::binary);

    if (!binaryFile) {
        std::cerr << "Error opening file for reading!" << std::endl;
        return;
    }

    Student students[3];

    // Read entire struct from binary file
    binaryFile.read(reinterpret_cast<char*>(students), sizeof(students));

    std::cout << "Student Records:" << std::endl;
    for (int i = 0; i < 3; ++i) {
        std::cout << "ID: " << students[i].id
                  << ", Name: " << students[i].name
                  << ", GPA: " << students[i].gpa << std::endl;
    }

    binaryFile.close();
}

int main() {
    // Write binary file
    writeBinaryFile();

    // Read binary file
    readBinaryFile();

    return 0;
}

Compile the program:

g++ binary_files.cpp -o binary_files

Run the executable:

./binary_files

Example output:

Binary file written successfully!
Student Records:
ID: 1, Name: John Doe, GPA: 3.5
ID: 2, Name: Alice Smith, GPA: 3.8
ID: 3, Name: Bob Johnson, GPA: 3.2

Key points about binary files:

  • Use std::ios::binary flag for binary mode
  • write() and read() methods for binary data
  • reinterpret_cast used to convert between types
  • Useful for storing structured data efficiently
  • Preserves exact binary representation of data

You can think of binary files like a precise blueprint. They store data exactly as it exists in memory, without any text conversion.

Position File Pointer with seekg/seekp

In this step, you'll learn how to manipulate file pointers using seekg() for reading and seekp() for writing in C++. These methods allow you to navigate and modify specific positions within a file.

Create a new C++ file called file_pointer.cpp:

touch ~/project/file_pointer.cpp

Add the following code to the file_pointer.cpp file:

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

void createSampleFile() {
    std::ofstream file("numbers.txt");
    for (int i = 1; i <= 10; ++i) {
        file << i << " ";
    }
    file.close();
}

void demonstrateSeekOperations() {
    // Open file in read and write mode
    std::fstream file("numbers.txt", std::ios::in | std::ios::out);

    if (!file) {
        std::cerr << "Error opening file!" << std::endl;
        return;
    }

    // Reading from different positions
    std::cout << "Reading operations:" << std::endl;

    // Move to the 5th byte (character position)
    file.seekg(5);
    int value;
    file >> value;
    std::cout << "Value at 5th byte: " << value << std::endl;

    // Move to the beginning of the file
    file.seekg(0);
    file >> value;
    std::cout << "First value: " << value << std::endl;

    // Writing at specific positions
    std::cout << "\nWriting operations:" << std::endl;

    // Move to a specific position and write
    file.seekp(0);
    file << "100 ";

    // Reset file pointer and read to verify
    file.seekg(0);
    file >> value;
    std::cout << "Modified first value: " << value << std::endl;

    file.close();
}

int main() {
    // Create a sample file with numbers
    createSampleFile();

    // Demonstrate seek operations
    demonstrateSeekOperations();

    return 0;
}

Compile the program:

g++ file_pointer.cpp -o file_pointer

Run the executable:

./file_pointer

Example output:

Reading operations:
Value at 5th byte: 4
First value: 1

Writing operations:
Modified first value: 10

Key points about file pointers:

  • seekg(): Moves read pointer (get pointer)
  • seekp(): Moves write pointer (put pointer)
  • First argument is byte position
  • Useful for random access in files
  • Can navigate to specific locations

You can think of file pointers like a cursor in a text editor. seekg() and seekp() help you move this cursor precisely where you want.

Close Files and Release Resources

In this step, you'll learn about the importance of properly closing files and managing resources in C++ to prevent memory leaks and ensure efficient file handling. You'll explore different methods of closing files and using RAII (Resource Acquisition Is Initialization) principles.

Create a new C++ file called file_resources.cpp:

touch ~/project/file_resources.cpp

Add the following code to the file_resources.cpp file:

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

// Manual file closing
void manualFileHandling() {
    std::ofstream outputFile("manual_file.txt");

    if (outputFile.is_open()) {
        outputFile << "Manually managed file resource" << std::endl;

        // Explicitly close the file
        outputFile.close();

        std::cout << "File closed manually." << std::endl;
    }
}

// RAII-based file handling using unique_ptr
void raii_fileHandling() {
    try {
        // Using unique_ptr to manage file resource
        std::unique_ptr<std::ofstream> file(new std::ofstream("raii_file.txt"));

        if (file && file->is_open()) {
            *file << "RAII-managed file resource" << std::endl;
            std::cout << "RAII file handling successful." << std::endl;
        }
        // File automatically closed when unique_ptr goes out of scope
    }
    catch (const std::exception& e) {
        std::cerr << "Error in RAII file handling: " << e.what() << std::endl;
    }
}

// Scope-based file handling
void scopeBasedFileHandling() {
    {
        // File will be automatically closed when it goes out of scope
        std::ofstream scopedFile("scoped_file.txt");

        if (scopedFile.is_open()) {
            scopedFile << "Scope-based file resource management" << std::endl;
            std::cout << "Scoped file handling successful." << std::endl;
        }
    } // File automatically closed here
}

int main() {
    // Demonstrate different file resource management techniques
    manualFileHandling();
    raii_fileHandling();
    scopeBasedFileHandling();

    return 0;
}

Compile the program:

g++ file_resources.cpp -o file_resources

Run the executable:

./file_resources

Example output:

File closed manually.
RAII file handling successful.
Scoped file handling successful.

Key points about closing files and managing resources:

  • Always close files after use
  • Use close() method for manual closing
  • Leverage RAII principles
  • Use scope-based resource management
  • Prevent resource leaks
  • Handle exceptions during file operations

You can think of file resources like borrowing a book from a library. Always return the book (close the file) when you're done to keep the library (system resources) organized.

Summary

In this lab, you learned how to open files in C++ using the ofstream and ifstream classes from the standard library. You explored the process of checking the file open status, writing text data to files, and reading data from text files. Additionally, you gained an understanding of handling file read/write errors, working with binary files using fstream, positioning the file pointer with seekg/seekp, and properly closing files and releasing resources. These fundamental file operations are essential for managing data storage and retrieval in C++ applications.

Other C++ Tutorials you may like