Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

C++  Module 14 – Input/output, files, formatting and time

File handling in C++: ifstream and ofstream

Read and write text and binary files with std::ifstream and std::ofstream, choose the right open mode, and catch every error from open to close.

  • Intermediate
  • 20 minutes
  • Examples run with Clang 21.0.0, GCC 16.2.0 and Python 3.14.8
  • By MySmartCoPilot
Free core, Pro depth: 7 of 20 minutes free
Free: The open mode decides what happens to a file that exists · A stream opens in its constructor and closes at the end of its block · Text mode changes line breaks on Windows, binary mode never does · 2 more sections. With a pass: 3 in-depth parts and 3 interview answers, about 13 minutes.

What you will learn

  • Read and write text and binary files with std::ifstream, std::ofstream and std::fstream
  • Choose an open mode such as app, trunc, ate, binary or noreplace for a task
  • Detect and report file errors at open, write and close time
  • Read a whole file into memory and copy binary files byte for byte

Before you start

A plain std::ofstream opened on notes.txt threw away its 11 bytes, first line and a line break, before the program had written anything. C++ reads and writes files through streams from <fstream>: std::ifstream reads, std::ofstream writes and std::fstream does both. Creating one opens the file, and its destructor: The member function written ~T(), with no parameters and no return type, that runs when an object's lifetime ends: at the closing brace of its block, on a return, during stack unwinding, or after main for a global. More in “Destructors and RAII in C++” closes it, so a stream declared inside a block cleans up after itself even when an exception leaves the block. Test the stream after opening, if (!in), because a missing file or a missing permission makes the open fail without an exception.

The The flags given when a file stream opens a file, such as std::ios::app or std::ios::binary. They decide whether an existing file is kept, emptied or refused, where writing starts, and whether line breaks are translated. decides what happens to a file that exists: an std::ofstream opened without one empties the file at once, std::ios::app appends to it, and C++23’s std::ios::noreplace refuses to touch it. Add std::ios::binary for data that must stay byte for byte as it is. Text and numbers then go in and out with <<, >>, std::getline and std::println, exactly as with the console.

The open mode decides what happens to a file that exists

Mode What it does to an existing file Typical use
out, or none for std::ofstream Empties it when it opens (the same as out with trunc) Writing a new report each time
app Keeps it, and every write goes to the end Logs and journals
in with out Keeps it, and writes overwrite bytes from the start; fails if there is no file Patching a fixed-size record
ate Keeps the mode’s other rules, and starts at the end Opening for reading or patching near the end
noreplace (C++23) Fails if the file exists Creating a file that must be new
binary No translation of line breaks Images, archives, any data that is not text

This program puts first line into notes.txt, opens it with each mode, writes something and prints the file afterwards, with its line breaks shown as \n:

Six open modes on a file that holds first line C++ · modes.cpp
// What each open mode does to a file that already holds "first line".
#include <filesystem>
#include <format>
#include <fstream>
#include <iterator>
#include <print>
#include <string>

// The whole file, with its line breaks shown as \n.
std::string contents(const char* path) {
    std::ifstream in(path, std::ios::binary);
    std::string text(std::istreambuf_iterator<char>(in), {});
    return std::format("{:?}", text);
}

void reset() { std::ofstream("notes.txt") << "first line\n"; }

int main() {
    reset();
    { std::ofstream out("notes.txt"); out << "new\n"; }
    std::println("{:<34} {}", "ofstream, no mode (out | trunc)", contents("notes.txt"));

    reset();
    { std::ofstream out("notes.txt", std::ios::app); out << "added\n"; }
    std::println("{:<34} {}", "app", contents("notes.txt"));

    reset();
    { std::ofstream out("notes.txt", std::ios::in | std::ios::out); out << "FIRST"; }
    std::println("{:<34} {}", "in | out (no truncation)", contents("notes.txt"));

    reset();
    { std::ofstream out("notes.txt", std::ios::in | std::ios::ate); out << "end\n"; }
    std::println("{:<34} {}", "in | ate (starts at the end)", contents("notes.txt"));

    reset();
    { std::ofstream out("notes.txt", std::ios::noreplace); std::println("{:<34} is_open() = {}", "noreplace (C++23), file exists", out.is_open()); }

    std::filesystem::remove("missing.txt");
    { std::fstream f("missing.txt", std::ios::in | std::ios::out); std::println("{:<34} is_open() = {}", "fstream in | out, no such file", f.is_open()); }
}

Output

ofstream, no mode (out | trunc)    "new\n"
app                                "first line\nadded\n"
in | out (no truncation)           "FIRST line\n"
in | ate (starts at the end)       "first line\nend\n"
noreplace (C++23), file exists     is_open() = false
fstream in | out, no such file     is_open() = false

Recorded with Apple clang version 21.0.0 (clang-2100.3.34.2) on macOS 26 arm64. To run it yourself: clang++ -std=c++23 -O2 -Wall -Wextra -Werror -pedantic -fsanitize=address,undefined modes.cpp -o modes && ./modes

Both libraries printed the same lines. The modes behaved as the table says: the plain std::ofstream kept only new, app kept the first line, in with out overwrote five bytes in place, and both noreplace on an existing file and fstream on a missing one failed to open. Step through the six opens, one mode at a time:

Interactive · step by step Six opens of notes.txt in modes.cpp Step through the opens. Before each one the file holds first line and a line break again; watch what each mode leaves.
Six opens of notes.txt in modes.cpp, step 7 of 7. Showing No mode: out | trunc, app, in | out, in | ate, noreplace (C++23), fstream: in | out, Before each open, notes.txt afterwards (left as it was), is_open() (false: no such file). In focus: fstream: in | out, is_open().No mode: out | truncthen writes newappthen writes addedin | outthen writes FIRSTin | atethen writes endnoreplace (C++23)on a file that existsfstream: in | outon missing.txtBefore each openfirst line\n, 11 bytesnotes.txt afterwardsleft as it wasis_open()false: no such file

The drawing shows the whole scene; its 7 steps are listed below.

Every step as text
  1. The starting file. Before every open, reset() writes first line and a line break into notes.txt: 11 bytes that each mode either keeps or throws away.
  2. No mode. A plain std::ofstream opens with out, which means out | trunc: the file is emptied the moment it opens, so after writing new it holds only that line.
  3. app. app keeps the file and moves to its end before every write, so added went after the first line.
  4. in | out. in with out keeps the file and starts at its first byte, so FIRST overwrote five bytes in place and the rest of the line stayed.
  5. in | ate. With in, nothing is emptied, and ate starts at the end, so end and a line break went after the first line.
  6. noreplace. noreplace refuses a file that already exists: the open failed, is_open() printed false, and notes.txt was not touched.
  7. A missing file. An std::fstream opened with in | out needs the file to exist. On missing.txt the open failed as well, so the program must test every open.

Checkpoint

Check: What each open mode does to a file

  1. Question 1 of 2 A program must change the first five bytes of an existing file and keep everything else. How should it open the file?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: std::ofstream with std::ios::in | std::ios::out

    Of the modes measured, only in | out keeps an existing file and writes from its first byte. It fails when the file does not exist, which is right for patching: there is nothing to patch.

  2. Question 2 of 2 std::ofstream out("notes.txt", std::ios::noreplace); runs while notes.txt holds a line. What happens?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: The open fails, is_open() is false, and the file keeps its line

    C++23's noreplace is the x of C's fopen: create a new file or fail. modes.cpp printed is_open() = false for an existing notes.txt with both compilers.

A stream opens in its constructor and closes at the end of its block

The second program writes a small CSV report with std::println, closes it, and reads it back field by field with std::getline:

A report written, closed and read back C++ · report.cpp
// Write a small CSV report, then read it back and check every row.
#include <fstream>
#include <ostream>   // std::println(out, ...) for streams is declared here
#include <print>
#include <sstream>
#include <string>
#include <vector>

struct Row {
    std::string city;
    int orders;
    double revenue;
};

int main() {
    std::vector<Row> rows{{"Pune", 412, 61850.5}, {"Kochi", 97, 12040.0}, {"Jaipur", 233, 30115.25}};
    {
        std::ofstream out("report.csv");
        if (!out) {
            std::println(stderr, "cannot create report.csv");
            return 1;
        }
        std::println(out, "city,orders,revenue");
        for (const Row& r : rows) std::println(out, "{},{},{:.2f}", r.city, r.orders, r.revenue);
    }   // out is closed here, which also writes whatever is still buffered

    std::ifstream in("report.csv");
    if (!in) {
        std::println(stderr, "cannot open report.csv");
        return 1;
    }
    std::string line;
    std::getline(in, line);   // the header
    double total = 0;
    int count = 0;
    while (std::getline(in, line)) {
        std::istringstream fields(line);
        std::string city, orders, revenue;
        std::getline(fields, city, ',');
        std::getline(fields, orders, ',');
        std::getline(fields, revenue);
        total += std::stod(revenue);
        ++count;
        std::println("{:<8} {:>4} orders {:>10}", city, orders, revenue);
    }
    std::println("{} rows read back, revenue {:.2f}", count, total);
}

Output

Pune      412 orders   61850.50
Kochi      97 orders   12040.00
Jaipur    233 orders   30115.25
3 rows read back, revenue 104005.75

Recorded with Apple clang version 21.0.0 (clang-2100.3.34.2) on macOS 26 arm64. To run it yourself: clang++ -std=c++23 -O2 -Wall -Wextra -Werror -pedantic -fsanitize=address,undefined report.cpp -o report && ./report

In the report, the block around the std::ofstream matters: its closing brace destroys the stream, which writes out the last buffered bytes and closes the file before the std::ifstream opens it. Step through the program and watch when the four lines really reach the file, and when the reading starts:

Interactive · message by message report.cpp writing report.csv, then reading it back Step through the program. Watch when the lines really reach the file, and why the reading starts only after that.
report.cpp writing report.csv, then reading it back, step 6 of 6. Messages so far: report.cpp to report.csv: open: create or empty; report.cpp to The stream: header and 3 rows; The stream to report.csv: 4 lines, then close; report.csv to report.cpp: Pune,412,61850.50.report.cpprevenue 104005.75The streamin reads report.csvreport.csv4 lines, closedopen: create or emptyheader and 3 rows4 lines, then closePune,412,61850.50

The drawing shows the whole scene; its 6 steps are listed below.

Every step as text
  1. Open for writing. std::ofstream out("report.csv") creates the file, or empties it if it is there already, and if (!out) checks that the open worked before anything is written.
  2. Lines into the buffer. std::println(out, …) writes the header and the three rows. They go into the stream's buffer first, so the file itself may still be empty.
  3. The closing brace. The block ends, so the destructor of out runs: it writes the buffered lines out to report.csv and closes the file.
  4. Open for reading. Only now does std::ifstream in("report.csv") open the file, so it finds every line. Had out still been open, the last lines could have been waiting in its buffer.
  5. Header, then rows. One std::getline skips the header. Each further line is split at its commas by std::getline(fields, …, ','), which stops at a comma and removes it.
  6. The total. std::stod turns each revenue into a double, and the program prints its three rows and 3 rows read back, revenue 104005.75, the same with both compilers.

One line is easy to forget: std::println(out, …) for a stream is declared in <ostream>, so include it yourself. GCC’s <fstream> happens to bring it along, but the libc++ of Apple clang 21 rejects the call, as this program without <ostream> shows:

no_ostream.cpp C++ · no_ostream.cpp
// std::println on an std::ofstream, with <fstream> and <print> included but <ostream> left out.
#include <fstream>
#include <print>

int main() {
    std::ofstream out("total.txt");
    std::println(out, "total {}", 42);
    std::println("wrote total.txt");
}
The same file built by both compilers Python · headers_session.py
from session import run

# no_ostream.cpp, which leaves out <ostream>, built with Apple clang (libc++), then with GCC 16 (libstdc++).
# Only the first three lines of each command's output are shown: the error, its line and the mark under it.
run("""
clang++ -std=c++23 -Wall -Wextra no_ostream.cpp -o no_ostream && ./no_ostream
g++-16 -std=c++23 -Wall -Wextra no_ostream.cpp -o no_ostream-gcc && ./no_ostream-gcc
""", max_lines=3)

Output

$ clang++ -std=c++23 -Wall -Wextra no_ostream.cpp -o no_ostream && ./no_ostream
no_ostream.cpp:7:5: error: no matching function for call to 'println'
    7 |     std::println(out, "total {}", 42);
      |     ^~~~~~~~~~~~
[13 more lines]
[exit status 1]
$ g++-16 -std=c++23 -Wall -Wextra no_ostream.cpp -o no_ostream-gcc && ./no_ostream-gcc
wrote total.txt

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 headers_session.py

Checkpoint

Check: Writing a file, closing it, reading it back

  1. Question 1 of 2 In report.cpp the std::ofstream lives in a block of its own that ends before the std::ifstream opens the file. Why?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: The block's end destroys the ofstream, which writes out its buffered lines and closes the file before reading starts

    A file stream opens in its constructor and closes in its destructor. Ending the writer's block is the plain way to say "the file is complete now"; out.close() inside the block would do the same.

  2. Question 2 of 2 Which header must a file include for std::println(out, …) with an std::ofstream, to build with both libraries?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: <ostream>

    Include what you use: <fstream> for the file streams and <ostream> for std::println on a stream, as report.cpp does. Relying on one library's indirect includes breaks the build with the other.

Text mode changes line breaks on Windows, binary mode never does

On Linux and macOS, text and binary mode behave the same. On Windows, text mode translates: writing turns each \n into the two bytes \r\n, reading turns \r\n back into \n, and a Ctrl+Z byte read in text mode ends the input. Text written and read on the same system survives that, but bytes of an image or a compressed file do not, so open every non-text file with std::ios::binary and read it with read() and gcount() rather than with >>.

On Windows Text mode Binary mode
Writing \n Two bytes, \r\n One byte, \n
Reading \r\n One \n Two bytes, \r and \n
Reading a Ctrl+Z byte The end of the input An ordinary byte

On Linux and macOS both columns behave like the binary one, which is why a missing std::ios::binary can stay hidden until the program is first built for Windows.

Checkpoint

Check: Text mode and binary mode

  1. Question 1 of 2 On Windows, a program writes "a\nb\nc\n" to a file opened in text mode. How many bytes does the file hold?

    Type a number.

    A hint

    Text mode on Windows writes each \n as two bytes.

    Show the answer: Question 1 of 2

    Answer: 9 bytes

    The text has three letters and three line breaks. Text mode writes each \n as \r\n, so the file holds 3 + 3 × 2 = 9 bytes; in binary mode, or on Linux and macOS, it holds 6.

  2. Question 2 of 2 Why should a program open an image file with std::ios::binary, even if it only runs on Linux today?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: On Windows, text mode would change bytes that happen to be line breaks or Ctrl+Z, and the same code would corrupt images there

    On POSIX systems the two modes behave the same. On Windows, text mode writes \n as \r\n, reads \r\n back as \n and ends the input at a Ctrl+Z byte, which corrupts any data that is not text.

Write errors usually show at flush or close, not at the write

A file error can appear at three moments, and only the first is easy to notice:

Written bytes go from the program to the stream buffer, then to the system at flush or close, then to the disk at fsync.std::ofstream out(path)is_open() is false whenthe file cannot be openedout << textusually only copies the bytesinto the stream's bufferThe stream's buffer,in the program's memoryThe operating system'scopy of the fileThe diskwhen the buffer fills,and at flush() or close():write errors show hereat fsync(), or later:until then, a power cutcan still lose the data

Where written bytes wait, and where each error appears

Text description of the diagram

The diagram follows the bytes of a write from the program to the disk, from top to bottom.

  1. Opening: std::ofstream out(path) asks the operating system for the file. If it cannot be opened, for example because a folder is missing or the file is read-only, is_open() is false.
  2. Writing: out << text usually only copies the bytes into the stream's buffer, a block of the program's own memory, so the write itself rarely reports a problem.
  3. The buffer is handed to the operating system when it fills up, and at flush() or close(). This is where write errors, such as a full disk, show up as failbit or badbit.
  4. The operating system keeps its own copy and writes it to the disk later, or at once when the program calls fsync(). Until then, a power cut can still lose data that the program has already written and closed.
  • At open, is_open() is false: the folder is missing, the name is wrong or the permission is missing.
  • At write, almost nothing is reported, because << usually only fills the stream’s buffer.
  • At flush or close, the buffer goes to the operating system, and a full disk or a quota sets failbit or badbit.

A destructor cannot report anything, so call close() yourself and test the stream afterwards wherever an incomplete file would be a problem. Writing the new version to a temporary file and renaming it over the old one, once it is complete, keeps a crash during a save from destroying the old file. With a stream, a whole file reads fastest when you ask for its size and call read() once.

Key idea

Test a file stream after it opens and again after you close it yourself: most write errors show only when the buffer is handed over at a flush or at close, and a destructor reports nothing.

Checkpoint

Check: Where file errors show up

  1. Question 1 of 2 A program writes a large report with out << line; and the disk fills up half-way. Where is the failure most likely to show?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: At a flush or at close(), when the buffered bytes go to the operating system

    The bytes of a write wait in the stream's buffer and reach the system when the buffer fills, at flush() or at close(). Check the stream after close() wherever an incomplete file would be a problem.

  2. Question 2 of 2 Why call close() yourself and test the stream afterwards, when the destructor closes the file anyway?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: A destructor cannot report anything, so a failure while it writes the last bytes goes unnoticed

    Errors from writing usually appear at flush or close, and the destructor swallows them. out.close() followed by a test of out turns a silent loss into a reported failure.

Practise: open modes, text mode and errors

Open modes, closing before reading, text and binary mode, and where errors surface: the questions below go over all four, starting from the one you know least, and ask any you miss once more at the end.

Practice that adapts to you

Practise this lesson

12 questions about 7 ideas of this lesson. Each answer is explained at once, and what you get right is kept in this browser.

  1. Question 1 of 12 notes.txt holds a week of notes. What does std::ofstream out("notes.txt"); do to it?

    Choose one answer.

    Show the answer: Question 1 of 12

    Answer: Empties it at once, before anything is written

    An std::ofstream opened without a mode uses out, which means out | trunc: the file is cut to zero bytes when it is opened. Use std::ios::app to append, or in | out to change bytes in place.

  2. Question 2 of 12 Which mode adds every write to the end of the file, whatever position the stream is at?

    Choose one answer.

    Show the answer: Question 2 of 12

    Answer: std::ios::app

    app moves to the end before every write. ate only starts at the end; after a seek, writes go wherever the stream points.

  3. Question 3 of 12 What does C++23's std::ios::noreplace do when the file already exists?

    Choose one answer.

    Show the answer: Question 3 of 12

    Answer: The open fails and is_open() returns false

    noreplace opens in exclusive mode, the x of C's fopen: the file must not exist yet. It closes the gap between checking that a name is unused and creating the file, during which another process could create it.

  4. Question 4 of 12 A program adds a line to a journal file on every run, and the journal must never get shorter. How should it open the file?

    Choose one answer.

    Show the answer: Question 4 of 12

    Answer: std::ofstream with std::ios::app

    For logs and journals, app is the mode: the existing lines stay, and every write lands at the end. ate only sets the starting position, and an ofstream without in still truncates.

  5. Question 5 of 12 When does an std::ofstream declared inside a block close its file?

    Choose one answer.

    Show the answer: Question 5 of 12

    Answer: At the end of the block, when its destructor runs

    Creating a file stream opens the file and destroying it closes the file, so a stream declared inside a block cleans up after itself at the closing brace.

  6. Question 6 of 12 std::getline(fields, city, ',') reads from the row Pune,412,61850.50. What happens to the first comma?

    Choose one answer.

    Show the answer: Question 6 of 12

    Answer: getline stops at it and removes it, without storing it in city

    With a delimiter as its third argument, getline reads up to that character, removes it and stores what came before it. report.cpp splits each row into city, orders and revenue this way.

  7. Question 7 of 12 What does std::ios::binary change on Linux and macOS?

    Choose one answer.

    Show the answer: Question 7 of 12

    Answer: Nothing: the two modes behave the same there

    On POSIX systems text and binary mode are the same, which is why code that forgets binary can work for years and then corrupt files the first time it is built for Windows.

  8. Question 8 of 12 Why should a program open an image file with std::ios::binary?

    Choose one answer.

    Show the answer: Question 8 of 12

    Answer: In text mode on Windows, line breaks are translated, so bytes that happen to be \n change

    On POSIX systems the two modes are the same. On Windows, text mode writes \n as \r\n and turns \r\n back into \n when reading, which corrupts any byte-exact data. Binary mode passes every byte through unchanged.

  9. Question 9 of 12 On Windows, a program writes "ok\n" in text mode and reads the file back in binary mode. Which bytes does it read?

    Choose one answer.

    Show the answer: Question 9 of 12

    Answer: o, k, \r and \n: four bytes

    A file written in one mode and read in the other shows the translation: the extra \r appears in binary mode. Read a file in the mode it was written in, and use binary for anything that is not text.

  10. Question 10 of 12 A program opens data/report.txt for writing, but the folder data does not exist. What does it see?

    Choose one answer.

    Show the answer: Question 10 of 12

    Answer: is_open() is false and the stream tests false; no exception is thrown

    Test every stream after opening, if (!out) or !out.is_open(), because a missing folder, a wrong name or a missing permission makes the open fail without an exception.

  11. Question 11 of 12 out << report; returned and out still tests true. Is the report on the disk?

    Choose one answer.

    Show the answer: Question 11 of 12

    Answer: Not necessarily; it may still be in the stream's buffer until flush() or close()

    A write usually copies the bytes into the buffer. They reach the operating system when the buffer fills or the stream is flushed or closed, and that is where a full disk is reported. Check the stream after close().

  12. Question 12 of 12 A save must never leave a half-written settings file, even when the disk fills up during the save. Which plan does that?

    Choose one answer.

    Show the answer: Question 12 of 12

    Answer: Write a temporary file, close it and test the stream, and only then rename it over the old file

    Writing the new version to a temporary file and renaming it over the old one, once it is complete and its close has been checked, keeps a failure during the save from destroying the old file.

Errors at open, write and close, reproduced on both libraries Pro: opens with a Pro, Premium or Ultimate pass

Each failure in this part is produced on purpose and run with both standard libraries, so you can see which flags and error numbers each one leaves and write checks that work with both.

In this part:

  • What a failed open tells you, and what errno adds
  • A full disk that only shows at close, reproduced with a file-size limit
  • Saving without ever losing the old file, with a crash reproduced

1 diagram · 6 runnable examples (C header, C++, Python) · about 6 minutes

Opening this part with your pass…

This part opens with any MySmartCoPilot pass.

  • Pro pass · 1 week₹79$2.99
  • 30 days₹179$5.99
  • 1 year₹1,699$45

One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.

It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).

Reading whole files and copying bytes, measured Pro: opens with a Pro, Premium or Ultimate pass

How a program reads a whole file can change its speed many times over without changing its result. This part times five common ways on a 20 MB file with both libraries and copies a binary file in a way that a checksum proves exact.

In this part:

  • Five ways to read 20 MB, timed on both libraries
  • When the size is not known in advance
  • A byte-exact copy, proved with a checksum

3 runnable examples (C++, Python) · about 4 minutes

Opening this part with your pass…

This part opens with any MySmartCoPilot pass.

  • Pro pass · 1 week₹79$2.99
  • 30 days₹179$5.99
  • 1 year₹1,699$45

One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.

It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).

Exercise: a tiny line-oriented database Pro: opens with a Pro, Premium or Ultimate pass

This exercise puts the whole lesson together: appending with the right mode, reading records back line by line, and rewriting a file so that a crash can never leave half of it.

In this part:

  • What the three functions must do
  • The starter, the sample tests and a first run
  • Rewriting the file safely when a record is removed

2 runnable examples (C header, C++, Python) · about 4 minutes

Opening this part with your pass…

This part opens with any MySmartCoPilot pass.

  • Pro pass · 1 week₹79$2.99
  • 30 days₹179$5.99
  • 1 year₹1,699$45

One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.

It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).

Interview questions

  1. Fresher · Warm-up

    What is the difference between opening a file with std::ios::app and with std::ios::ate?

    Both start at the end of an existing file, but only app keeps every write there. With app, each write first moves to the end, so a log opened in append mode can never overwrite what is already in it, even after a seek. ate only places the position at the end once, when the file opens; after that the stream behaves as its other mode bits say, so a seek can move it and later writes go wherever the position points. There is one more trap: ate does not stop truncation, so an std::ofstream opened with ate alone still empties the file, because its mode is out, which truncates. Combine ate with in, as in in | ate, to keep the contents.

  2. Mid to senior

    A desktop app saves settings with std::ofstream out(path); out << settings;. Some users report that after a crash or a power cut their settings file is empty or cut short. Explain how that happens and design a save that never loses the old settings.

    Model answer, Pro. Model answers open with any pass; prices are in the notice on this page. First step and follow-ups

  3. Mid to senior

    A service writes its audit log through an std::ofstream and never checks the stream. When the disk filled up, the log silently stopped and nobody noticed for days. Where do write errors show up with file streams, and how would you make the logger notice and report them?

    Model answer, Pro. First step and follow-ups

  4. Fresher to mid

    A file-copy function written with std::ifstream and std::ofstream copies images correctly on Linux and macOS, but on Windows the copies are corrupted and slightly larger. Explain why, fix it, and say how you would prove that a copy is exact.

    Model answer, Pro. First step and follow-ups

Key takeaways

  • std::ifstream, std::ofstream and std::fstream open in their constructor and close in their destructor; test the stream after opening.
  • An std::ofstream without a mode empties the file; use app to append, in with out to patch, noreplace to create only.
  • Open every file that is not text with std::ios::binary, because text mode on Windows translates line breaks.
  • Errors from writing usually appear at flush or close, so close the file yourself and check the stream afterwards.

References

Related tools

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.