What Is It?
What Is File Handling in C++?
File handling allows C++ programs to read data from files and write data to files on disk. Instead of losing all data when a program terminates, you can persist student records, configuration settings, logs, and any structured data to files.
C++ provides file handling through the <fstream> header, which defines three stream classes:
- ifstream (input file stream): Read from files
- ofstream (output file stream): Write to files
- fstream (file stream): Both read and write
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main() {
// Write to a file
ofstream outFile("students.txt");
outFile << "Arjun 85" << endl;
outFile << "Priya 92" << endl;
outFile << "Kiran 78" << endl;
outFile.close();
// Read from the file
ifstream inFile("students.txt");
string name;
int marks;
while (inFile >> name >> marks) {
cout << name << " scored " << marks << endl;
}
inFile.close();
return 0;
}File streams inherit from the same iostream hierarchy as cin and cout. Everything Raghav knows about <<, >>, getline, and stream state applies directly to file streams.
Why Does It Matter?
Why Is File Handling Important?
1. Data Persistence
Without files, all program data is lost when the program exits. File handling lets Arjun save student records, configuration settings, and computation results that survive beyond the program's lifetime.
2. Practical Applications
Nearly every real-world application involves files: reading configuration files, parsing CSV data, logging errors, saving game state, processing large datasets that do not fit in memory, and communicating between programs through files.
3. Binary File I/O for Performance
Text files are human-readable but slow for large data. Binary files store data in the same format as memory, making reads and writes significantly faster. Database engines, image processors, and serialization libraries all use binary I/O.
4. Foundation for Advanced Topics
Understanding file streams prepares you for network streams, string streams (stringstream), and the C++17 <filesystem> library. The iostream abstraction is the same -- once you understand file I/O, you understand all C++ I/O.
5. Competitive Programming and Interviews
While competitive programming typically uses cin/cout, many online judges and companies use file-based I/O (freopen). Interview questions often involve parsing files, implementing CSV readers, or building config file parsers.
Detailed Explanation
Detailed Explanation
1. Opening and Closing Files
Files can be opened through the constructor or the open() method:
#include <iostream>
#include <fstream>
using namespace std;
int main() {
// Method 1: Open via constructor
ofstream file1("output.txt");
file1 << "Hello from constructor" << endl;
file1.close();
// Method 2: Open via open()
ofstream file2;
file2.open("output2.txt");
if (file2.is_open()) {
file2 << "Hello from open()" << endl;
file2.close();
} else {
cerr << "Failed to open file" << endl;
}
// Destructor auto-closes, but explicit close is good practice
{
ofstream file3("output3.txt");
file3 << "Auto-closed when file3 goes out of scope";
} // file3.close() called automatically here
return 0;
}2. File Modes
File modes control how a file is opened:
| Mode | Description |
|---|---|
| ios::in | Open for reading (default for ifstream) |
| ios::out | Open for writing (default for ofstream, truncates file) |
| ios::app | Append to end of file (does not truncate) |
| ios::binary | Binary mode (no text translation) |
| ios::trunc | Truncate file to zero length on open |
| ios::ate | Seek to end after opening |
#include <fstream>
using namespace std;
int main() {
// Truncate and write (default for ofstream)
ofstream f1("data.txt");
f1 << "First write" << endl;
f1.close();
// Append mode: adds to existing content
ofstream f2("data.txt", ios::app);
f2 << "Appended line" << endl;
f2.close();
// Binary mode for raw data
ofstream f3("data.bin", ios::binary);
int num = 42;
f3.write(reinterpret_cast<char*>(&num), sizeof(num));
f3.close();
// Combining modes with |
fstream f4("data.txt", ios::in | ios::out | ios::app);
f4.close();
return 0;
}3. Reading Line by Line (getline) and Word by Word (>>)
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main() {
// Create a test file
ofstream out("poem.txt");
out << "Twinkle twinkle little star" << endl;
out << "How I wonder what you are" << endl;
out.close();
// Read line by line
ifstream in1("poem.txt");
string line;
cout << "Line by line:" << endl;
while (getline(in1, line)) {
cout << " " << line << endl;
}
in1.close();
// Read word by word
ifstream in2("poem.txt");
string word;
cout << "Word by word:" << endl;
while (in2 >> word) {
cout << "[" << word << "] ";
}
cout << endl;
in2.close();
return 0;
}4. Checking File State
#include <iostream>
#include <fstream>
using namespace std;
int main() {
ifstream file("nonexistent.txt");
// is_open(): was the file successfully opened?
if (!file.is_open()) {
cerr << "Could not open file" << endl;
}
// Stream state flags
ifstream f("test.txt");
// f.good() -- no errors
// f.eof() -- end of file reached
// f.fail() -- logical error (e.g., reading int but found string)
// f.bad() -- serious I/O error (e.g., disk failure)
// Common pattern: read until failure
ifstream data("numbers.txt");
int num;
while (data >> num) {
cout << num << " ";
}
if (data.eof()) cout << "\nReached end of file" << endl;
if (data.fail()) cout << "Read failed (format error or EOF)" << endl;
return 0;
}5. Binary File I/O
#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;
struct Student {
char name[50];
int age;
double gpa;
};
int main() {
// Write binary
Student s1;
strcpy(s1.name, "Arjun");
s1.age = 20;
s1.gpa = 8.5;
Student s2;
strcpy(s2.name, "Priya");
s2.age = 21;
s2.gpa = 9.2;
ofstream out("students.dat", ios::binary);
out.write(reinterpret_cast<char*>(&s1), sizeof(Student));
out.write(reinterpret_cast<char*>(&s2), sizeof(Student));
out.close();
// Read binary
ifstream in("students.dat", ios::binary);
Student temp;
while (in.read(reinterpret_cast<char*>(&temp), sizeof(Student))) {
cout << temp.name << ", Age: " << temp.age
<< ", GPA: " << temp.gpa << endl;
}
in.close();
return 0;
}6. File Position: seekg, seekp, tellg, tellp
#include <iostream>
#include <fstream>
using namespace std;
int main() {
// seekg: set get (read) position
// seekp: set put (write) position
// tellg: get current read position
// tellp: get current write position
ofstream out("seektest.txt");
out << "ABCDEFGHIJ";
out.close();
ifstream in("seektest.txt");
// Read from position 3
in.seekg(3); // move to 4th byte (0-indexed)
char ch;
in.get(ch);
cout << "At position 3: " << ch << endl; // D
// Tell current position
cout << "Current position: " << in.tellg() << endl; // 4
// Seek from end
in.seekg(-3, ios::end);
in.get(ch);
cout << "3 from end: " << ch << endl; // H
// Seek from current position
in.seekg(1, ios::cur);
in.get(ch);
cout << "Skip 1 from current: " << ch << endl; // J
// Get file size
in.seekg(0, ios::end);
cout << "File size: " << in.tellg() << " bytes" << endl;
in.close();
return 0;
}7. Practical Example: CSV Reader/Writer
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
struct Student {
string name;
int age;
double gpa;
};
void writeCSV(const string& filename, const vector<Student>& students) {
ofstream file(filename);
file << "Name,Age,GPA" << endl; // header
for (const auto& s : students) {
file << s.name << "," << s.age << "," << s.gpa << endl;
}
file.close();
}
vector<Student> readCSV(const string& filename) {
vector<Student> students;
ifstream file(filename);
string line;
getline(file, line); // skip header
while (getline(file, line)) {
stringstream ss(line);
Student s;
string token;
getline(ss, s.name, ',');
getline(ss, token, ',');
s.age = stoi(token);
getline(ss, token, ',');
s.gpa = stod(token);
students.push_back(s);
}
file.close();
return students;
}
int main() {
vector<Student> students = {
{"Arjun", 20, 8.5}, {"Priya", 21, 9.2}, {"Kiran", 19, 7.8}
};
writeCSV("students.csv", students);
auto loaded = readCSV("students.csv");
for (const auto& s : loaded) {
cout << s.name << ", Age: " << s.age << ", GPA: " << s.gpa << endl;
}
return 0;
}8. Practical Example: Config File Parser
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <map>
using namespace std;
map<string, string> parseConfig(const string& filename) {
map<string, string> config;
ifstream file(filename);
string line;
while (getline(file, line)) {
// Skip empty lines and comments
if (line.empty() || line[0] == '#') continue;
size_t pos = line.find('=');
if (pos != string::npos) {
string key = line.substr(0, pos);
string value = line.substr(pos + 1);
config[key] = value;
}
}
file.close();
return config;
}
int main() {
// Create a config file
ofstream out("app.conf");
out << "# Application Config" << endl;
out << "db_host=localhost" << endl;
out << "db_port=3306" << endl;
out << "app_name=StudentPortal" << endl;
out << "debug=true" << endl;
out.close();
auto config = parseConfig("app.conf");
for (auto& [key, value] : config) {
cout << key << " = " << value << endl;
}
return 0;
}
Code Examples
No code examples available yet.
Common Mistakes
No common mistakes listed for this topic.
Summary
Summary coming soon.