LearnContact
Lesson 2910 min read

File Handling

So far, data used in programs has existed temporarily in memory. In this lesson, you will learn how C++ uses file streams to create, write, read, append, and permanently store data in files.

Introduction

In the previous lesson, you learned about exception handling. So far, most of the data used in our programs has been stored temporarily in memory.

Consider a variable such as int marks = 90. While the program is running, the value exists in memory. When the program terminates, that variable no longer exists.

Temporary Data
int marks = 90;

std::cout << marks;

For small learning programs, temporary data is often enough. Real applications, however, usually need information to remain available after the program closes.

Student System

Student names, marks, attendance, and course records must remain available.

Banking System

Account and transaction records must survive program restarts.

Game

Player progress, settings, and high scores may need to be saved.

Application

Documents and user-created information must remain available later.

Program Creates Data
Store Data in File
Program Ends
Open Program Later
Read Saved Data
Persistent Data

File handling allows a program to store information outside its temporary runtime memory so that the information can be accessed later.

What is File Handling?

File handling is the process of creating, opening, reading, writing, updating, and managing data stored in files.

Unlike ordinary local variables, file contents can remain available after a program terminates because the data is stored on persistent storage.

Basic File Handling Concept
Program
   │
   ├── Write ─────► File
   │
   └── Read ◄───── File
OperationPurpose
CreateCreate a new file when required
OpenConnect a stream to a file
WriteStore data in the file
ReadRetrieve data from the file
AppendAdd new data after existing content
CloseEnd the connection between the stream and file
Simple Definition

File handling allows a program to store data in files and retrieve that data later.

Why Do We Need File Handling?

Programs often need data to survive beyond a single execution. Without persistent storage, users would need to recreate the same information every time an application starts.

Without File Handling

  • Program data exists only temporarily.
  • Information is lost after termination.
  • Users may need to enter the same data again.
  • Long-term records cannot be maintained.
  • Programs cannot easily exchange saved data.

With File Handling

  • Data can remain available after termination.
  • Previously saved information can be loaded.
  • New information can be added to existing records.
  • Applications can maintain long-term data.
  • Files can exchange data between compatible programs.

Persistent Storage

Save information for future program executions.

Data Retrieval

Load previously stored information when needed.

Record Updates

Add or modify stored information.

Data Exchange

Use files as an exchange format between programs.

Historical Records

Maintain logs, reports, transactions, and other long-term records.

Configuration

Store settings that can be loaded when an application starts.

Real-World Analogy

Imagine writing information on a whiteboard. The information is useful while it remains on the board, but it can easily disappear when the board is erased.

Now imagine writing the same information in a notebook. You can close the notebook, keep it safely, and open it again later to read the same information.

Whiteboard — Temporary

  • Useful for current work.
  • Information can disappear.
  • Comparable to temporary runtime data.
  • Not intended for long-term storage.

Notebook — Persistent

  • Information can be kept.
  • Content can be read later.
  • Comparable to file storage.
  • Useful for long-term records.
Real-World ConceptProgramming Concept
WhiteboardTemporary runtime storage
NotebookFile
Writing notesWriting data
Reading notesReading data
Adding a new pageAppending data
Write Information
Store It
Close Application
Open Later
Read Information

File Streams in C++

C++ performs file input and output through streams. The standard <fstream> header provides the main file stream classes.

Required Header
#include <fstream>

1️⃣ std::ifstream

Input file stream. Commonly used for reading data from files.

2️⃣ std::ofstream

Output file stream. Commonly used for writing data to files.

3️⃣ std::fstream

General file stream. Can be used for both input and output when opened with suitable modes.

ClassFull MeaningCommon Purpose
std::ifstreamInput File StreamReading
std::ofstreamOutput File StreamWriting
std::fstreamFile StreamReading and writing
Stream Direction
Reading:

File ─────────► Program
       ifstream


Writing:

Program ───────► File
       ofstream


Reading + Writing:

Program ◄──────► File
        fstream
Streams Connect Programs and Files

A file stream object provides the interface through which a C++ program communicates with a file.

Opening a File

Before reading or writing file data, a program needs a file stream associated with the target file.

One approach is to create the stream object first and then call its open() member function.

Opening with open()
#include <fstream>

std::ofstream file;

file.open("student.txt");

Another common approach is to provide the file name directly when constructing the stream object.

Opening with the Constructor
std::ofstream file(
    "student.txt"
);

Using open()

  • Create the stream object first.
  • Open the file later.
  • Useful when the file name is determined later.

Using Constructor

  • Create and open in one statement.
  • More concise.
  • Common when the file name is already known.
Include <fstream>
Create Stream Object
Open File
Check Stream State
Perform File Operation

Example 1: Writing to a File

The following program creates an output file stream and writes text to a file.

Example 1: Writing to a File
#include <iostream>
#include <fstream>

int main()
{
    std::ofstream file(
        "student.txt"
    );

    if (!file)
    {
        std::cout
            << "Unable to open file";

        return 1;
    }

    file << "Rahul";

    file.close();

    return 0;
}

How the Program Works

  • The <fstream> header provides std::ofstream.
  • An output stream named file is created.
  • The stream attempts to open student.txt.
  • The stream state is checked.
  • The insertion operator writes Rahul to the file.
  • The file is explicitly closed.
Writing Flow
Program
   │
   ▼
std::ofstream
   │
   ▼
student.txt
   │
   ▼
Write "Rahul"
student.txt
Rahul
Default Output Behavior

Opening a file with std::ofstream using its normal default mode typically truncates an existing file. Existing content can therefore be replaced.

Example 2: Reading from a File

The std::ifstream class is commonly used to read data from a file.

Example 2: Reading from a File
#include <iostream>
#include <fstream>
#include <string>

int main()
{
    std::ifstream file(
        "student.txt"
    );

    if (!file)
    {
        std::cout
            << "Unable to open file";

        return 1;
    }

    std::string name;

    file >> name;

    std::cout << name;

    file.close();

    return 0;
}

How the Program Works

  • An input file stream attempts to open student.txt.
  • The program checks whether the stream is usable.
  • A string variable named name is created.
  • The extraction operator reads formatted text.
  • The value is displayed on the console.
  • The stream is closed.
Reading Flow
student.txt
     │
     ▼
 std::ifstream
     │
     ▼
std::string name
     │
     ▼
Console Output
Output
Rahul
Formatted Extraction

The >> operator reads formatted input. For strings, it normally stops at whitespace, so getline() is better when complete lines containing spaces are required.

Example 3: Writing and Reading Multiple Lines

Files often contain multiple records or lines. The following program first writes several names and then reads them back line by line.

Example 3: Multiple Lines
#include <iostream>
#include <fstream>
#include <string>

int main()
{
    std::ofstream outFile(
        "student.txt"
    );

    if (!outFile)
    {
        std::cout
            << "Unable to open file";

        return 1;
    }

    outFile << "Rahul\n";
    outFile << "Amit\n";
    outFile << "Priya\n";

    outFile.close();

    std::ifstream inFile(
        "student.txt"
    );

    if (!inFile)
    {
        std::cout
            << "Unable to open file";

        return 1;
    }

    std::string line;

    while (std::getline(inFile, line))
    {
        std::cout
            << line
            << '\n';
    }

    inFile.close();

    return 0;
}

Writing Phase

  • The output stream opens student.txt.
  • Three names are written on separate lines.
  • The output stream is closed.

Reading Phase

  • The input stream opens the same file.
  • getline() attempts to read one complete line.
  • The loop continues while each read succeeds.
  • Every successfully read line is displayed.
File Content
Rahul
Amit
Priya
Output
Rahul
Amit
Priya
Preferred Reading Loop

Use while (std::getline(file, line)) when reading a text file line by line. The read operation itself determines whether the loop should continue.

Appending Data

Sometimes existing file content must be preserved while new information is added at the end. C++ provides append mode for this purpose.

Opening in Append Mode
std::ofstream file(
    "student.txt",
    std::ios::app
);
Appending a New Record
#include <iostream>
#include <fstream>

int main()
{
    std::ofstream file(
        "student.txt",
        std::ios::app
    );

    if (!file)
    {
        std::cout
            << "Unable to open file";

        return 1;
    }

    file << "Suresh\n";

    file.close();

    return 0;
}

Normal Output Opening

  • Existing content may be truncated.
  • Previous data can be lost.
  • Suitable when replacing file contents.

Append Mode

  • Existing content is preserved.
  • New output is written at the end.
  • Suitable for logs and additional records.
Before Append
Rahul
Amit
Priya
After Append
Rahul
Amit
Priya
Suresh
Preserve Line Structure

When appending text records, make sure the existing file ends where you expect. A missing newline can cause new text to appear directly beside previous content.

File Opening Modes

File opening modes control how a stream interacts with a file.

ModePurpose
std::ios::inOpen for input operations
std::ios::outOpen for output operations
std::ios::appWrite output at the end of the file
std::ios::ateOpen and initially position at the end
std::ios::truncDiscard existing contents when opening
std::ios::binaryPerform file operations in binary mode
Input Mode
std::fstream file(
    "data.txt",
    std::ios::in
);
Output Mode
std::fstream file(
    "data.txt",
    std::ios::out
);
Input and Output Modes
std::fstream file(
    "data.txt",
    std::ios::in |
    std::ios::out
);
Binary Input Mode
std::ifstream file(
    "image.bin",
    std::ios::binary
);
Modes Can Be Combined

Compatible opening modes can be combined with the bitwise OR operator to configure a stream for multiple behaviors.

Checking File Status

A program should verify that a file operation is ready to proceed before depending on the stream.

Checking with is_open()
std::ifstream file(
    "student.txt"
);

if (file.is_open())
{
    std::cout
        << "File opened successfully";
}
else
{
    std::cout
        << "Unable to open file";
}

A stream can also be tested directly in a condition.

Checking Stream State
std::ifstream file(
    "student.txt"
);

if (!file)
{
    std::cout
        << "Unable to open file";

    return 1;
}
CheckPurpose
file.is_open()Checks whether the stream currently has an associated open file
if (file)Checks whether the stream is currently in a usable state
if (!file)Detects a failed or unusable stream state
Attempt to Open File
Check Stream
Open Successful?
Perform Operation or Handle Failure
Opening Is Not the Only Operation That Can Fail

A file can open successfully and later encounter read or write errors. Robust programs also consider the stream state during file operations.

Program Execution Flow

A typical file-handling program follows a sequence of creating a stream, opening or associating it with a file, validating the stream, performing operations, and finishing safely.

Program Starts
Create File Stream
Open File
Check Stream State
Read or Write
Finish File Operation
Program Ends
Complete File Handling Flow
Program Starts
      │
      ▼
Create Stream Object
      │
      ▼
Open File
      │
      ▼
Opening Successful?
   ┌──┴──┐
   │     │
  No    Yes
   │     │
   ▼     ▼
Handle   Read / Write
Failure      │
             ▼
        Check Operation
             │
             ▼
        Finish Stream Use
             │
             ▼
         Program Ends
StepPurpose
1Include the required file stream header
2Create the appropriate stream object
3Associate the stream with a file
4Verify that the stream is usable
5Read or write data
6Handle failures when necessary
7Close explicitly when early release is required or allow RAII cleanup
Streams Use RAII

Standard file stream objects close their associated files when the stream objects are destroyed. Explicit close() is still useful when you need to release the file before the stream object reaches the end of its lifetime.

Memory vs File Storage

Runtime memory and file storage serve different purposes. Variables are useful for active computation, while files are useful when data must remain available later.

Storage Comparison
Runtime Memory
┌────────────────────┐
│ marks = 90         │
│ name = "Rahul"     │
└────────────────────┘
          │
          │ Program Ends
          ▼
   Runtime Data Gone


Persistent File
┌────────────────────┐
│ student.txt        │
│                    │
│ Rahul              │
│ Amit               │
│ Priya              │
└────────────────────┘
          │
          │ Program Ends
          ▼
   File Remains
FeatureRuntime MemoryFile Storage
LifetimeUsually tied to program executionCan remain after program termination
SpeedGenerally very fastGenerally slower than memory access
PurposeActive computationPersistent data storage
Typical ExamplesVariables and objectsDocuments, records, logs, settings
AccessDirectly through program dataThrough file input/output operations

Runtime Memory

  • Used during active execution.
  • Ideal for calculations and working data.
  • Data lifetime depends on program and object lifetime.
  • Generally faster to access.

File Storage

  • Used for persistent information.
  • Can survive program termination.
  • Useful for records and saved state.
  • Requires input and output operations.

Real-World Applications

File handling is used whenever applications need to preserve, exchange, import, export, or log information.

Student Management

Store student records, attendance, marks, and reports.

Banking

Maintain exported records, transaction reports, and logs.

Hospital Systems

Store exported patient information, reports, and application records.

Game Development

Save game progress, settings, and high scores.

Configuration Files

Store application preferences and startup settings.

Logging Systems

Record events, warnings, diagnostics, and errors.

Data Processing

Import and export text, CSV, and other data formats.

Editors

Create, open, modify, and save documents.

Application Generates Data
Serialize or Format Data
Write to File
Store Persistently
Read Later
Files Are One Form of Persistence

Large applications may also use databases, cloud storage, and specialized storage systems. File handling remains a fundamental concept behind persistent input and output.

Advantages of File Handling

Persistent Storage

Information can remain available after the program terminates.

Retrieval

Previously stored data can be loaded later.

Record Keeping

Applications can maintain logs, reports, and historical information.

Data Exchange

Files can transfer compatible information between programs.

Configuration

Applications can preserve settings and preferences.

Import and Export

Programs can exchange data through common file formats.

  • Stores information beyond a single program execution.
  • Allows previously saved data to be retrieved.
  • Supports text and binary data.
  • Allows records to be appended.
  • Supports application configuration.
  • Enables logging and diagnostics.
  • Supports import and export workflows.
  • Allows compatible programs to exchange data.
  • Works with sequential and position-based file access.
  • Provides the foundation for understanding persistent input and output.

Common Beginner Mistakes

Forgetting <fstream>

File stream classes are declared in the <fstream> header.

Ignoring Open Failure

The program assumes the file is available without checking the stream.

Accidentally Overwriting Data

Opening an output file with truncating behavior can destroy existing content.

Using >> for Full Lines

Formatted string extraction stops at whitespace and does not read an entire line.

Using while (!file.eof())

Testing eof() before attempting a read can process invalid or stale data.

Ignoring Write Failures

A stream may encounter an error after opening successfully.

Missing Header
// ❌ Missing:
// #include <fstream>

std::ifstream file(
    "data.txt"
);
Ignoring File Failure
// ❌ Risky
std::ifstream file(
    "missing.txt"
);

std::string data;
file >> data;
Checking Before Reading
// ✅ Better
std::ifstream file(
    "data.txt"
);

if (!file)
{
    std::cout
        << "Unable to open file";

    return 1;
}
Incorrect EOF Loop
// ❌ Avoid
while (!file.eof())
{
    std::getline(file, line);

    std::cout << line;
}
Correct Reading Loop
// ✅ Better
while (std::getline(file, line))
{
    std::cout
        << line
        << '\n';
}
Do Not Assume Success

File operations depend on external resources such as paths, permissions, storage devices, and available space. Always consider failure.

Best Practices

  • Include <fstream> when using file stream classes.
  • Choose std::ifstream for input and std::ofstream for output when only one direction is required.
  • Use std::fstream when both input and output are genuinely needed.
  • Check whether opening succeeded before depending on the file.
  • Check stream state when read or write operations matter.
  • Use getline() for complete text lines.
  • Use the read operation itself as the loop condition.
  • Avoid while (!file.eof()) loops.
  • Use append mode only when preserving existing content is required.
  • Understand whether the selected mode truncates existing content.
  • Use binary mode for binary file operations.
  • Use explicit close() when the file must be released before the stream object is destroyed.
  • Otherwise, rely on stream object lifetime and RAII for automatic cleanup.
  • Keep file paths configurable when building larger applications.
  • Use meaningful file formats for structured data.
  • Validate data read from external files.
  • Do not trust file contents simply because the file opened successfully.
  • Handle missing files and permission failures gracefully.
  • Use exception handling when it fits the application error-handling strategy.
  • Avoid storing sensitive information in plain text without appropriate protection.
Safe Line-by-Line Reading
#include <iostream>
#include <fstream>
#include <string>

int main()
{
    std::ifstream file(
        "student.txt"
    );

    if (!file)
    {
        std::cerr
            << "Unable to open file";

        return 1;
    }

    std::string line;

    while (std::getline(file, line))
    {
        std::cout
            << line
            << '\n';
    }

    if (!file.eof())
    {
        std::cerr
            << "File reading failed";

        return 1;
    }

    return 0;
}

Weak File Handling

  • Assume every file opens.
  • Ignore stream failures.
  • Overwrite files accidentally.
  • Use incorrect reading loops.

Better File Handling

  • Check stream state.
  • Choose opening modes carefully.
  • Use read operations as loop conditions.
  • Handle external failures deliberately.

Frequently Asked Questions

What is file handling?

File handling is the process of creating, opening, reading, writing, updating, and managing data stored in files.

Why do programs use files?

Files allow information to remain available after a program terminates.

Which header is required for file streams?

The <fstream> header provides the main standard file stream classes.

What is std::ifstream?

std::ifstream is an input file stream commonly used for reading from files.

What is std::ofstream?

std::ofstream is an output file stream commonly used for writing to files.

What is std::fstream?

std::fstream is a general file stream that can perform input and output when opened with suitable modes.

How can a file be opened?

A file can be associated with a stream through the stream constructor or the open() member function.

How do I check whether a file opened successfully?

You can check the stream state directly or use is_open() when you specifically need to know whether a file is associated with the stream.

What does std::ios::app do?

It opens the stream so output is written at the end of the file.

What does std::ios::trunc do?

It discards existing file contents when the file is opened with truncating behavior.

What does std::ios::binary do?

It opens the file in binary mode.

Can opening modes be combined?

Yes. Compatible modes can be combined using the bitwise OR operator.

What is the difference between >> and getline()?

The >> operator performs formatted extraction and usually stops string input at whitespace, while getline() reads an entire line.

Why should while (!file.eof()) be avoided?

eof() becomes true only after a read attempts to go past the end. The read operation itself should usually control the loop.

Must every file stream call close() explicitly?

No. Standard file streams close their associated files when the stream objects are destroyed. Explicit close() is useful when the file must be released earlier.

Does a successful open guarantee all later operations succeed?

No. Reads and writes can fail after a file has opened successfully.

What happens when std::ofstream opens an existing file normally?

Its normal output behavior typically truncates the existing file unless another mode such as append is used.

Can files store binary data?

Yes. Files can store binary data, and std::ios::binary is used for binary-mode operations.

Can two programs use the same file format?

Yes, if both programs understand and correctly process the same file structure and encoding.

Are files the only way to store persistent data?

No. Applications also use databases, cloud storage, and other persistence systems, but file handling is a fundamental storage concept.

Key Takeaways

  • File handling allows programs to store and retrieve persistent data.
  • Runtime variables and persistent files serve different purposes.
  • The <fstream> header provides standard file stream classes.
  • std::ifstream is commonly used for file input.
  • std::ofstream is commonly used for file output.
  • std::fstream can support both input and output.
  • A stream can open a file through its constructor or open().
  • Programs should check whether file operations are ready to proceed.
  • The insertion operator can write formatted data.
  • The extraction operator can read formatted data.
  • getline() reads complete lines.
  • Read operations should usually control reading loops.
  • while (!file.eof()) is a common incorrect pattern.
  • Append mode preserves existing content and writes at the end.
  • Normal output opening may truncate existing file content.
  • Opening modes control stream behavior.
  • Compatible modes can be combined.
  • Binary mode is used for binary file operations.
  • Opening success does not guarantee every later operation succeeds.
  • File streams participate in RAII.
  • Stream destruction automatically closes associated files.
  • Explicit close() is useful when early release is required.
  • Files can store records, settings, logs, and saved application state.
  • External file data should be validated.
  • File paths, permissions, and storage conditions can cause failures.
  • Good file handling requires deliberate error checking and appropriate opening modes.

Summary

File handling allows C++ programs to store information beyond a single program execution and retrieve that information later.

The <fstream> header provides std::ifstream for input, std::ofstream for output, and std::fstream for combined input and output operations.

A stream can be associated with a file through its constructor or the open() member function. Before depending on a file operation, programs should verify that the stream is in an appropriate state.

The insertion operator writes formatted data, while the extraction operator reads formatted input. When complete lines are required, std::getline() is usually the better choice.

Opening modes determine how files are accessed. Append mode preserves existing content and writes new output at the end, while truncating behavior replaces previous content.

A successful file opening does not guarantee that every later read or write will succeed. Robust programs consider stream state throughout important file operations.

Standard file streams use RAII, so their associated files are closed automatically when the stream objects are destroyed. Explicit close() remains useful when a file must be released before the end of the stream object lifetime.

Files are used for saved application state, logs, reports, configuration, import and export, and many other persistent data requirements.

By understanding file streams, opening methods, reading, writing, appending, stream states, opening modes, and safe reading patterns, you now have the foundation required to build C++ programs that preserve and retrieve information.

You have now completed the current 30-lesson C++ programming course, covering the journey from programming fundamentals to functions, arrays, pointers, object-oriented programming, templates, namespaces, exception handling, and persistent file storage.

C++ Course Completed!

Congratulations! You have completed all 30 lessons in the C++ Programming course.

Back to C++ Course