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
ClassDirectionDefault modeTypical use
ifstreamRead onlyios::inReading config files, parsing data
ofstreamWrite onlyios::out | ios::truncWriting reports, saving results
fstreamRead and writeNone, must specifyUpdating 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?