C++: File Handling
Learn how to open, read, write, and manage files using C++ file streams, file modes, position pointers, and binary I/O.
File Streams
C++ handles files through three stream classes defined in <fstream>. Each is a specialization for a specific direction of data flow. Using them mirrors console I/O with cin and cout, but the source or destination is a file on disk instead of the terminal.
Three File Stream Classes
Include <fstream> to access all three. Each wraps the file handle and manages opening, buffering, and closing automatically when the object goes out of scope.
- ifstream: input file stream, reads from a file
- ofstream: output file stream, writes to a file
- fstream: bidirectional stream, reads and writes the same file
- All three inherit from the same base, so they share the same operators and status methods
| Class | Direction | Default mode | Typical use |
|---|---|---|---|
| ifstream | Read only | ios::in | Reading config files, parsing data |
| ofstream | Write only | ios::out | ios::trunc | Writing reports, saving results |
| fstream | Read and write | None, must specify | Updating records in place |
Opening and Closing Files
A file can be opened by passing the filename to the constructor or by calling open() explicitly. Always verify with is_open() before reading or writing. Call close() when done, or let the stream object go out of scope, the destructor closes it automatically.
Opening and Closing
Always check is_open() after opening. An unopened stream silently produces no output and reads nothing, making bugs hard to find.
- Constructor shorthand: ofstream file("data.txt");
- Explicit open: file.open("data.txt");
- Check success: if (!file.is_open()) { handle error }
- Close: file.close(); frees the file handle immediately rather than waiting for the destructor
Opening and Writing a File
C++Open the file, check is_open(), write with <<, then close. notes.txt is created in the working directory.
File Modes
A file mode flag tells the stream how to open the file. Flags can be combined with the bitwise OR operator |. The mode is passed as the second argument to the constructor or open().
File Mode Flags
Choose the mode that matches your intent. Using ios::out without ios::app truncates the file silently, which can cause accidental data loss.
- ios::in: open for reading
- ios::out: open for writing (truncates existing content by default)
- ios::app: append, all writes go to the end, existing content preserved
- ios::trunc: discard existing content on open
- ios::binary: binary mode, no newline translation
- ios::ate: start at end of file but allow seeks to any position
Append Mode
C++ios::out creates or truncates. ios::app adds to the end. Running this twice keeps all entries.
Writing to Files
Writing to a file with << works exactly like writing to cout. For binary data, use write() which copies raw bytes directly without any text formatting.
Writing Methods
Use << for text files. Use write() for binary files where you need to store structured data exactly as it is laid out in memory.
- Text write: file << value, formats the value as text, same as cout
- Binary write: file.write(reinterpret_cast<char*>(&data), sizeof(data))
- Both methods return the stream, so you can chain: file << a << " " << b
- Flush explicitly with file.flush() or file << endl (which also flushes)
Writing Student Records
C++Each student is written as one text line. The file can be opened in any text editor.
Reading from Files
Reading with >> extracts one whitespace-delimited token at a time. getline() reads a full line including spaces. Use a while loop with the stream condition to read until end-of-file.
Reading Methods
Use >> for word-by-word parsing. Use getline() whenever the data may contain spaces, such as names or full sentences.
- Token read: file >> word, stops at any whitespace
- Line read: getline(file, line), reads the whole line into a string
- Loop pattern: while (getline(file, line)) { process line; }
- Check EOF: file.eof() returns true after the last read hit the end of the file
Reading Student Records
C++Read name and grade pairs until EOF, then compute the average.
Reading Full Lines with getline
When lines may contain spaces, for example, full names, sentences, or CSV rows, getline() is the right tool. It reads everything up to the newline character and stores it in a string, discarding the newline itself.
getline(stream, string)
getline() is the standard way to read a line of text from a file. It handles spaces and tabs inside the line without splitting them into separate tokens.
- Signature: getline(inputStream, stringVariable)
- Returns the stream, use directly in a while condition: while (getline(f, line))
- A third argument sets a custom delimiter: getline(f, token, ',')
- After mixing >> and getline, call file.ignore() to consume the leftover newline
Writing then Reading Full Lines
C++getline reads the whole line including spaces. Each line is printed with its line number.
File Position Pointers
Every open file has a read position (get pointer) and a write position (put pointer). You can query and reposition these to jump to any byte in the file. This allows random access: reading or overwriting a specific record without rewriting the entire file.
Position Pointer Methods
tellg/tellp return the current position. seekg/seekp move it. The second argument is an anchor: ios::beg, ios::cur, or ios::end.
- tellg(): return current read position (bytes from start)
- seekg(pos): move read position to byte pos from the beginning
- seekg(offset, anchor): move relative to ios::beg, ios::cur, or ios::end
- tellp() / seekp(): same, but for the write position
seekg and tellg
C++Jump to byte 6 to read World, then rewind to the start to read Hello.
Checking File Status
File streams carry a set of state flags that reflect what has happened during I/O. Checking them lets you detect errors early and handle missing files gracefully instead of silently producing wrong output.
Status Methods
Check is_open() before any I/O. Use the stream directly as a condition in loops, it evaluates to false when eof or an error is reached.
- is_open(): true if the file opened successfully
- eof(): true after a read that hit the end of the file
- fail(): true if the last operation failed (type mismatch, eof)
- good(): true only if no error flags are set
- clear(): reset all error flags so the stream can be used again
File Status and Word/Line Count
C++is_open() guards against a missing file. eof() confirms the loop ended cleanly.
Binary File Handling
Binary mode stores data as raw bytes with no text formatting. This is more compact and faster for structured data like records, images, or serialized objects. Use write() and read() to transfer whole structs in one call.
Binary I/O with write() and read()
write() and read() transfer sizeof(T) raw bytes. reinterpret_cast<char*> is required to treat any struct as a byte array.
- Write: file.write(reinterpret_cast<char*>(&obj), sizeof(obj));
- Read: file.read(reinterpret_cast<char*>(&obj), sizeof(obj));
- Open with ios::binary to disable newline translation on Windows
- Structs with pointers or std::string cannot be safely binary-serialized, use plain old data types only
Binary Write and Read
C++The entire Record struct is written as raw bytes and read back into a fresh struct.
Copying a File
Combining an input and an output stream lets you copy a file line by line. This pattern transfers every byte from the source file to the destination, preserving newlines and special characters.
File Copy Pattern
Open the source as ifstream and the destination as ofstream, then loop with getline until EOF. Add a newline after each line to preserve the original line endings.
- Open source with ifstream, destination with ofstream
- Loop: while (getline(src, line)) dst << line << '\n';
- For binary copy, use read/write in a char buffer loop for better performance
- Always verify both files opened before transferring data
Copy File Line by Line
C++Every line from source.txt is written to copy.txt. The line count is reported at the end.
Knowledge Check
1. Which stream class is used to write to a file in C++?
2. Which file mode flag appends new data to the end of an existing file instead of overwriting it?
3. What does getline(file, line) do?
4. Which method checks whether a file was opened successfully?
5. What does seekg(0, ios::beg) do?
6. Which flag combination opens a file for both reading and writing?
7. What is the correct way to open a binary file for reading?
8. Which method returns true when the end of a file has been reached?