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.
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.
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.
Program
│
├── Write ─────► File
│
└── Read ◄───── File| Operation | Purpose |
|---|---|
| Create | Create a new file when required |
| Open | Connect a stream to a file |
| Write | Store data in the file |
| Read | Retrieve data from the file |
| Append | Add new data after existing content |
| Close | End the connection between the stream and file |
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 Concept | Programming Concept |
|---|---|
| Whiteboard | Temporary runtime storage |
| Notebook | File |
| Writing notes | Writing data |
| Reading notes | Reading data |
| Adding a new page | Appending data |
File Streams in C++
C++ performs file input and output through streams. The standard <fstream> header provides the main file stream classes.
#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.
| Class | Full Meaning | Common Purpose |
|---|---|---|
| std::ifstream | Input File Stream | Reading |
| std::ofstream | Output File Stream | Writing |
| std::fstream | File Stream | Reading and writing |
Reading:
File ─────────► Program
ifstream
Writing:
Program ───────► File
ofstream
Reading + Writing:
Program ◄──────► File
fstreamA 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.
#include <fstream>
std::ofstream file;
file.open("student.txt");Another common approach is to provide the file name directly when constructing the stream object.
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.
Example 1: Writing to a File
The following program creates an output file stream and writes text 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.
Program
│
▼
std::ofstream
│
▼
student.txt
│
▼
Write "Rahul"RahulOpening 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.
#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.
student.txt
│
▼
std::ifstream
│
▼
std::string name
│
▼
Console OutputRahulThe >> 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.
#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.
Rahul
Amit
PriyaRahul
Amit
PriyaUse 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.
std::ofstream file(
"student.txt",
std::ios::app
);#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.
Rahul
Amit
PriyaRahul
Amit
Priya
SureshWhen 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.
| Mode | Purpose |
|---|---|
| std::ios::in | Open for input operations |
| std::ios::out | Open for output operations |
| std::ios::app | Write output at the end of the file |
| std::ios::ate | Open and initially position at the end |
| std::ios::trunc | Discard existing contents when opening |
| std::ios::binary | Perform file operations in binary mode |
std::fstream file(
"data.txt",
std::ios::in
);std::fstream file(
"data.txt",
std::ios::out
);std::fstream file(
"data.txt",
std::ios::in |
std::ios::out
);std::ifstream file(
"image.bin",
std::ios::binary
);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.
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.
std::ifstream file(
"student.txt"
);
if (!file)
{
std::cout
<< "Unable to open file";
return 1;
}| Check | Purpose |
|---|---|
| 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 |
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 Stream Object
│
▼
Open File
│
▼
Opening Successful?
┌──┴──┐
│ │
No Yes
│ │
▼ ▼
Handle Read / Write
Failure │
▼
Check Operation
│
▼
Finish Stream Use
│
▼
Program Ends| Step | Purpose |
|---|---|
| 1 | Include the required file stream header |
| 2 | Create the appropriate stream object |
| 3 | Associate the stream with a file |
| 4 | Verify that the stream is usable |
| 5 | Read or write data |
| 6 | Handle failures when necessary |
| 7 | Close explicitly when early release is required or allow RAII cleanup |
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.
Runtime Memory
┌────────────────────┐
│ marks = 90 │
│ name = "Rahul" │
└────────────────────┘
│
│ Program Ends
▼
Runtime Data Gone
Persistent File
┌────────────────────┐
│ student.txt │
│ │
│ Rahul │
│ Amit │
│ Priya │
└────────────────────┘
│
│ Program Ends
▼
File Remains| Feature | Runtime Memory | File Storage |
|---|---|---|
| Lifetime | Usually tied to program execution | Can remain after program termination |
| Speed | Generally very fast | Generally slower than memory access |
| Purpose | Active computation | Persistent data storage |
| Typical Examples | Variables and objects | Documents, records, logs, settings |
| Access | Directly through program data | Through 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.
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
File stream classes are declared in the <fstream> header.
The program assumes the file is available without checking the stream.
Opening an output file with truncating behavior can destroy existing content.
Formatted string extraction stops at whitespace and does not read an entire line.
Testing eof() before attempting a read can process invalid or stale data.
A stream may encounter an error after opening successfully.
// ❌ Missing:
// #include <fstream>
std::ifstream file(
"data.txt"
);// ❌ Risky
std::ifstream file(
"missing.txt"
);
std::string data;
file >> data;// ✅ Better
std::ifstream file(
"data.txt"
);
if (!file)
{
std::cout
<< "Unable to open file";
return 1;
}// ❌ Avoid
while (!file.eof())
{
std::getline(file, line);
std::cout << line;
}// ✅ Better
while (std::getline(file, line))
{
std::cout
<< line
<< '\n';
}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.
#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.