optional · CSS study notes
18. Files & Streams
- A stream is a sequence of bytes flowing between a program and a source/destination (file, console, etc.)
ifstream— input file stream (reading);ofstream— output file stream (writing);fstream— both
| Flag | Meaning |
|---|---|
ios::in | Open for reading |
ios::out | Open for writing |
ios::app | Append — writes go to the end, existing content preserved |
ios::ate | Open and immediately seek to the end (unlike app, you CAN seek elsewhere afterward) |
ios::trunc | Discard existing content on open (default with ios::out) |
ios::binary | Open in binary mode — required for raw struct/class I/O |
#include <fstream>
ofstream fout("data.txt");
fout << "Hello CSS aspirant" << endl;
fout.close();
Stream classes, laid out
| Class | Purpose | Header |
|---|---|---|
ifstream | Input file stream — reading from a file | <fstream> |
ofstream | Output file stream — writing to a file | <fstream> |
fstream | Both input and output on the same file | <fstream> |
cin/cout | Standard input/output streams (console) | <iostream> |
Files and console I/O share the same <</>> operator syntax — this uniformity is intentional, part of the stream abstraction.
Opening, writing, and always closing
#include <fstream>
#include <iostream>
using namespace std;
int main()
{
ofstream fout("notes.txt"); // opens (creates if missing) for writing
if (!fout) // ALWAYS check the stream opened successfully
{
cout << "Failed to open file!";
return 1;
}
fout << "First line" << endl;
fout << "Second line" << endl;
fout.close(); // always close -- flushes buffered data to disk
return 0;
}
Open mode flags — combining with |
ofstream fout("log.txt", ios::app); // append, don't overwrite
fstream file("data.dat", ios::in | ios::out | ios::binary); // combine multiple flags
| Flag | Meaning |
|---|---|
ios::in | Open for reading |
ios::out | Open for writing |
ios::app | Append — writes go to the end, existing content preserved |
ios::ate | Open and seek to end immediately (but you CAN still seek elsewhere afterward) |
ios::trunc | Discard existing content on open |
ios::binary | Binary mode — required for raw struct/class I/O |
Important MCQs
- Which stream class is used for reading from a file?
- a) ofstream b) ifstream c) sstream d) cout
- Which open-mode flag discards existing file content when opening?
- a) ios::app b) ios::ate c) ios::trunc d) ios::binary
- Which flag is required for raw struct/class binary I/O?
- a) ios::app b) ios::ate c) ios::trunc d) ios::binary
ios::appdiffers fromios::atein that:- a) They are identical b) ios::app always appends writes to the end; ios::ate seeks to the end once, but you can then seek elsewhere c) ios::ate is for reading only d) ios::app is binary only
Self-Test Questions
- Why should you always check
if (!fout)after opening a file stream? - What happens if you forget to call
.close()on a file stream? - What's the difference between
ios::appandios::ate?
📌 Sample & Repeated FPSC Questions (2016–2026)
2020, Paper I, Q5(b) (15 marks) — Write C++ programs to compute following: i. Add a student ii. Add a course iii. Find a student with respect to CGPA iv. Add a Teacher v. Update a student.
This is FPSC's flagship file-I/O question of the last decade, and it is already solved in full on the Classes and Objects — Exam Practice → "University Records System" page. From this page's Files & Streams angle, here's what it actually tests — the open-mode choice for each operation:
- Add a student / course / teacher —
ofstreamopened withios::app | ios::binary: appends a new record without disturbing existing ones. - Find a student by CGPA —
ifstreamopened withios::binary, loopingfin.read(...)until end-of-file: pure scanning, nothing is modified. - Update a student — a single
fstreamopened withios::in | ios::out | ios::binary: needs both read and write on the same stream to locate, then overwrite, an existing record.
ofstream fout("students.dat", ios::app | ios::binary); // "Add a student"
fout.write((char*)&s, sizeof(Student));
Records are written/read as raw binary structs (ios::binary) throughout, since text-mode <</>> cannot reliably round-trip a struct.
Exam angle: whenever FPSC gives a "design a class + persist it to file" prompt, the mode-flag choice (app vs in|out vs plain out) is worth as many marks as the class design itself — see this page's flag table above for the full reference.
📜 Past-Paper Questions & MCQs (CSS 2016–2026)
2020 · Paper-I · Q5(b) · 15 marks
Q. The university data is stored in files. Write C++ functions to (i) add a student, (ii) add a course, (iii) find a student by CGPA, (iv) add a teacher, (v) update a student.
Ans.
#include <iostream>
#include <fstream>
using namespace std;
struct Student { int id; char name[30]; int age; char address[40]; char contact[15]; char program[20]; float cgpa; };
struct Teacher { int id; char name[30]; int age; char address[40]; char degree[20]; char subjects[40]; float salary; };
struct Course { char semester[10]; char code[10]; int studentId; int teacherId; char grade[3]; };
void addStudent() { // (i)
Student s;
cout << "ID Name Age Address Contact Program CGPA: ";
cin >> s.id >> s.name >> s.age >> s.address >> s.contact >> s.program >> s.cgpa;
ofstream f("students.dat", ios::binary | ios::app);
f.write((char*)&s, sizeof(s));
}
void addCourse() { // (ii)
Course c;
cin >> c.semester >> c.code >> c.studentId >> c.teacherId >> c.grade;
ofstream f("courses.dat", ios::binary | ios::app);
f.write((char*)&c, sizeof(c));
}
void addTeacher() { // (iv)
Teacher t;
cin >> t.id >> t.name >> t.age >> t.address >> t.degree >> t.subjects >> t.salary;
ofstream f("teachers.dat", ios::binary | ios::app);
f.write((char*)&t, sizeof(t));
}
void findByCGPA(float minCgpa) { // (iii)
ifstream f("students.dat", ios::binary);
Student s;
while (f.read((char*)&s, sizeof(s)))
if (s.cgpa >= minCgpa) cout << s.id << " " << s.name << " " << s.cgpa << endl;
}
void updateStudent(int id) { // (v)
fstream f("students.dat", ios::binary | ios::in | ios::out);
Student s;
while (f.read((char*)&s, sizeof(s)))
if (s.id == id) {
cout << "New CGPA: "; cin >> s.cgpa;
f.seekp(-(long)sizeof(s), ios::cur); // go back one record
f.write((char*)&s, sizeof(s)); // overwrite it
break;
}
}
- Idea: records are stored as fixed-size structures in binary files. Adding appends a record, searching reads records in order, and updating moves the file pointer back one record with
seekpand overwrites it.