C++ File Handling Input/Output Operations
Data Persistence

C++ File Handling: Complete Guide with Examples

Master C++ file handling: fstream, ofstream, ifstream operations. Learn text/binary file operations, file pointers, error handling, serialization, and best practices.

fstream

Input & Output

ifstream

Input Only

ofstream

Output Only

Binary Files

Raw Data

C++ Tutorial · File Handling

Persist data beyond program lifetime with file streams. Learn opening modes, reading/writing text, binary files, and checking stream errors—skills used in logs, configs, and data pipelines.

What you will learn

  • Open files with correct ios modes
  • Read and write text line by line
  • Use binary mode when needed
  • Check fail(), eof(), and good() bits
  • Close streams via RAII destructors

Why this topic matters

File I/O appears in assignments, tools, and backend services. Interviewers ask about modes, RAII, and error handling.

Key terms & indexing

C++ file handling ifstream ofstream C++ read write file fstream C++

Introduction to File Handling

File handling in C++ allows programs to store data permanently on disk, read existing data, and perform various file operations. It's essential for data persistence, configuration storage, and data exchange between programs.

Why File Handling?
  • Data persistence beyond program execution
  • Configuration and settings storage
  • Data exchange between programs
  • Logging and audit trails
  • Database and large data storage
  • Backup and recovery systems
File Stream Classes
  • fstream: Input and output operations
  • ifstream: Input (reading) operations only
  • ofstream: Output (writing) operations only
  • ios: Base class for all stream classes
  • Header: #include <fstream>
File Handling Process Flow
1
Open File: Create file stream object and open file
2
Check Status: Verify file opened successfully
3
Read/Write: Perform file operations
4
Error Handling: Check for errors during operations
5
Close File: Release file resources

C++ File Stream Classes

The following table compares all file stream classes in C++ with their purposes, methods, and characteristics:

Class Purpose Key Methods Use Cases
fstream Both input and output operations open(), close(), read(), write(), seekg(), seekp() Read/write operations, file updates
ifstream Input operations only (reading) open(), close(), get(), getline(), read(), eof() Reading configuration, data processing
ofstream Output operations only (writing) open(), close(), put(), write(), flush() Logging, data storage, report generation
File Modes Specify how file is opened ios::in, ios::out, ios::app, ios::binary, ios::trunc Control file access behavior
Text Files Human-readable data <<, >>, getline() Configuration files, logs, CSV data
Binary Files Raw data storage read(), write() Images, databases, serialized objects

1. File Opening Modes

File modes determine how a file is opened and what operations are allowed. They control whether to read, write, append, create new files, or handle binary data.

File Mode Flags
// Common file mode flags:
ios::in      // Open for reading (input)
ios::out     // Open for writing (output)
ios::app     // Append to end of file
ios::ate     // Open and seek to end
ios::trunc   // Truncate file if it exists
ios::binary  // Open in binary mode

// Combinations:
ios::in | ios::out      // Read and write
ios::out | ios::trunc   // Write and truncate
ios::out | ios::app     // Write and append
ios::in | ios::binary   // Read binary data

File Mode Examples

1. ios::in
ifstream in("data.txt");
2. ios::out
ofstream out("out.txt");
3. app mode
ofstream log("log.txt", ios::app);
4. binary
fstream f("b.dat", ios::binary);
5. in|out
fstream io("db.txt", ios::in|ios::out);
6. trunc
ofstream w("x.txt", ios::trunc);
Mode Selection Guidelines:
  • ios::in | ios::out: Read and write existing file
  • ios::out | ios::trunc: Create new or overwrite
  • ios::out | ios::app: Append without overwriting
  • ios::in | ios::binary: Read binary data
  • ios::ate: Useful for log files
  • Combine modes using bitwise OR (|)
Common Mistakes:
  • Forgetting to check if file opened successfully
  • Using wrong mode for intended operation
  • Not closing files after use
  • Opening non-existent file for reading
  • File permission issues
  • Path/directory doesn't exist

2. Text File Operations

Text files store data in human-readable format. C++ provides various methods for reading and writing text files using stream operators and functions.

Basic Text File Operations
// Writing to text file
ofstream outFile("file.txt");
outFile << "Text data" << endl;
outFile << variable << " " << anotherVar;

// Reading from text file
ifstream inFile("file.txt");
string line;
while(getline(inFile, line)) {
    cout << line << endl;
}

// Reading word by word
string word;
while(inFile >> word) {
    cout << word << endl;
}

Text File Examples

1. Write lines
ofstream o("t.txt");
o << "Hello
";
2. Read word
ifstream i("t.txt");
string w; i>>w;
3. getline
string line;
while(getline(i,line))
4. Check open
if(!i.is_open()) return 1;
5. Close file
i.close();
6. Append line
ofstream a("t.txt",ios::app);
a<<"More";

Text File Best Practices

  • Always check if file opened successfully
  • Close files when done to free resources
  • Use getline() for reading entire lines
  • Handle different line endings (Windows vs Unix)
  • Validate data when reading from files
  • Use proper error handling for file operations

3. Binary File Operations

Binary files store data in raw binary format, preserving exact byte representations. They're efficient for storing complex data structures, images, and serialized objects.

Binary File Operations
// Writing binary data
ofstream binFile("data.bin", ios::binary);
int data = 42;
binFile.write((char*)&data, sizeof(data));

// Reading binary data
ifstream readBin("data.bin", ios::binary);
int readData;
readBin.read((char*)&readData, sizeof(readData));

// Working with structures
struct Data {
    int id;
    char name[50];
    double value;
};

Data d = {1, "Example", 3.14};
binFile.write((char*)&d, sizeof(d));

Binary File Examples

1. write struct
ofstream o("b.dat",ios::binary);
o.write((char*)&s,sizeof s);
2. read struct
ifstream i("b.dat",ios::binary);
i.read((char*)&s,sizeof s);
3. write int
int n=42;
o.write((char*)&n,sizeof n);
4. read vector
i.read(buf, n*sizeof(int));
5. tellg size
i.seekg(0,ios::end);
streampos sz=i.tellg();
6. goback start
i.seekg(0,ios::beg);
Text Files
  • Human readable
  • Larger file size
  • Slower processing
  • Platform dependent line endings
  • Easy to debug
  • Good for configuration
Binary Files
  • Machine readable
  • Smaller file size
  • Faster processing
  • Platform independent
  • Preserves exact data
  • Good for databases

4. File Pointers and Positioning

File pointers track read/write positions in files. C++ provides functions to manipulate these pointers for random access operations.

tellg() & tellp()

Get current position of get/put pointers.

ifstream file("data.txt");
streampos pos = file.tellg();
cout << "Current position: " << pos;
seekg() & seekp()

Set position of get/put pointers.

// Move to position 100
file.seekg(100);

// Move from current position
file.seekg(50, ios::cur);

// Move from end
file.seekg(-20, ios::end);
Positioning Constants

Reference points for seeking.

ios::beg  // Beginning of file
ios::cur  // Current position
ios::end  // End of file

// Examples:
seekg(0, ios::beg);  // Beginning
seekg(0, ios::end);  // End
seekg(-10, ios::cur); // Back 10 bytes

File Pointer Examples

1. tellg position
streampos p = f.tellg();
2. seekg read
f.seekg(10, ios::beg);
3. seekp write
f.seekp(0, ios::end);
4. skip bytes
f.seekg(4, ios::cur);
5. rewind
f.clear();
f.seekg(0);
6. end minus n
f.seekg(-8, ios::end);
File Pointer Best Practices:
  • Always check if seek operations succeeded
  • Use ios::beg for absolute positioning
  • Use ios::cur for relative positioning
  • Use ios::end for operations from file end
  • Remember that binary and text modes affect positioning
  • Clear error flags before positioning operations

5. Error Handling in File Operations

Proper error handling is crucial for robust file operations. C++ provides several methods to detect and handle file operation errors.

Error Checking Methods
// 1. Using is_open()
ifstream file("data.txt");
if (!file.is_open()) {
    cerr << "Failed to open file!";
    return 1;
}

// 2. Using fail()
if (file.fail()) {
    cerr << "File operation failed!";
}

// 3. Using good()
while (file.good()) {
    // Safe to read
}

// 4. Using eof()
while (!file.eof()) {
    // Read until end of file
}
Stream State Methods
// Check stream state
if (file.rdstate() == ios::goodbit) {
    // All good
}

if (file.rdstate() & ios::failbit) {
    // Non-fatal error
}

if (file.rdstate() & ios::badbit) {
    // Fatal error
}

// Clear error state
file.clear();

// Set exception mask
file.exceptions(ios::failbit | ios::badbit);

Error Handling Examples

1. fail bit
if (f.fail()) cerr<<"fail";
2. eof check
while(getline(f,line)) {}
if(f.eof())
3. bad open
if(!f) cerr<<"no file";
4. clear flags
f.clear();
5. exceptions
f.exceptions(ios::failbit);
6. perror style
if(!f.is_open()) return 1;
Error Handling Best Practices:
  • Always check is_open() after opening a file
  • Use good() before read/write operations
  • Check eof() after reading to detect end of file
  • Use clear() to reset error states when appropriate
  • Consider using exceptions for critical errors
  • Log errors with descriptive messages and error codes
  • Implement retry logic for transient errors

6. Object Serialization

Serialization is the process of converting objects into a format that can be stored or transmitted. In C++, this often means writing object data to files.

Serialization Examples

1. Save Student
o<<s.id<<" "<<s.name<<"
";
2. Load Student
i>>s.id>>s.name;
3. Binary record
o.write((char*)&rec,sizeof rec);
4. Version field
o<<"v1
";
5. Vector count
o<<v.size(); for(auto x:v)o<<x;
6. Validate read
if(!i) throw runtime_error("bad");
Serialization Considerations:
  • Binary serialization is not portable across different architectures
  • Always include version information in serialized data
  • Handle pointer and reference members carefully
  • Consider using established formats (JSON, XML, Protocol Buffers)
  • Validate deserialized data to prevent security issues
  • Implement backward compatibility for data format changes

7. Best Practices and Common Mistakes

Best Practices
  • Always check if file opened successfully
  • Close files in reverse order of opening
  • Use RAII principles for file handling
  • Specify full paths or handle relative paths carefully
  • Use appropriate file modes for intended operations
  • Implement proper error handling and logging
  • Validate data read from files
Common Mistakes
  • Not closing files (resource leaks)
  • Assuming file operations always succeed
  • Using text mode for binary data
  • Not checking for EOF correctly
  • Buffer overflows when reading strings
  • Not handling different line endings
  • Race conditions in multi-threaded file access

Good vs Bad File Examples

1. BAD: no close
ofstream f("x.txt");
// missing close
2. GOOD: RAII
ofstream f("x.txt");
// closes at }
3. BAD: no check
ifstream i("nope.txt");
i>>x;
4. GOOD: is_open
if(!i.is_open()) return;
5. BAD: text for binary
f<< structObj;
6. GOOD: write bytes
f.write((char*)&obj,sizeof obj);

Frequently asked questions

What is the difference between text and binary mode?

Text mode may translate newlines; binary reads/writes raw bytes—use binary for non-text formats.

Do I need to call close()?

Destructors close automatically—close early only if you must reopen the same stream object.

How do I read an entire file into a string?

Use stringstream with rdbuf(), or read line by line for large files to save memory.