Skip to content
C++ Better Explained
Go back
How to Read a File Line by Line in C++

How to Read a File Line by Line in C++

Short answer: open an std::ifstream and loop with while (std::getline(file, line)). That reads one line per iteration, strips the newline, and stops cleanly at the end of the file.


The Minimal Version

#include <iostream>
#include <fstream>
#include <string>

int main() {
    std::ifstream file("data.txt");

    if (!file) {
        std::cerr << "Could not open data.txt\n";
        return 1;
    }

    std::string line;
    while (std::getline(file, line)) {
        std::cout << line << '\n';
    }
}

That is the whole pattern, and it is the one to memorise. getline returns the stream, which converts to false when a read fails — including at end of file — so the loop terminates on its own.

Always Check the File Opened

Skipping the if (!file) check is the most common reason a beginner’s file program “does nothing”. If the path is wrong, ifstream fails silently, the getline loop never executes even once, and the program exits with no output and no error.

std::ifstream file("data.txt");
if (!file.is_open()) {          // same thing as if (!file)
    std::cerr << "Open failed\n";
    return 1;
}

Relative paths are resolved from the directory you run the program in, not where the source file lives — which explains most mysterious open failures inside IDEs.

Learning C++ properly? The C++ Better Explained Ebook covers file handling, strings and the STL in plain English — 87 pages, just $19.

Never Use while (!file.eof())

You will see this in old tutorials. It is wrong:

// BROKEN — processes the last line twice
while (!file.eof()) {
    std::getline(file, line);
    std::cout << line << '\n';
}

eof() only turns true after a read has already run off the end. So the final iteration reads nothing, leaves line holding the previous value (or empty), and you print one line too many. Putting getline in the loop condition tests the read itself, which is why the correct version has no such bug.

Reading All Lines into a Vector

Often you want the whole file in memory:

#include <vector>

std::vector<std::string> readLines(const std::string& path) {
    std::vector<std::string> lines;
    std::ifstream file(path);
    std::string line;
    while (std::getline(file, line)) {
        lines.push_back(line);
    }
    return lines;
}

int main() {
    auto lines = readLines("data.txt");
    std::cout << "Read " << lines.size() << " lines\n";
    for (const auto& l : lines) std::cout << l << '\n';
}

Now you can index, sort or search the lines like any other vector.

Parsing Each Line

Lines usually contain fields. Feed each one into a stringstream:

#include <sstream>

std::string line;
while (std::getline(file, line)) {
    std::istringstream ss(line);
    std::string name;
    int score;
    if (ss >> name >> score) {
        std::cout << name << " scored " << score << '\n';
    }
}

For comma-separated fields, use the three-argument getline with a delimiter:

std::istringstream ss(line);
std::string field;
while (std::getline(ss, field, ',')) {
    std::cout << "[" << field << "] ";
}

That is the core of reading a CSV file.

Skipping Blank Lines and Comments

while (std::getline(file, line)) {
    if (line.empty()) continue;
    if (line[0] == '#') continue;   // comment line
    process(line);
}

If the file came from Windows and you are reading it on Linux, each line may end with a stray \r. Strip it:

if (!line.empty() && line.back() == '\r') {
    line.pop_back();
}

This one causes genuinely baffling bugs — string comparisons fail for no visible reason because the invisible carriage return is still there.

Counting Lines

int count = 0;
std::string line;
while (std::getline(file, line)) ++count;
std::cout << "Lines: " << count << '\n';

Note that you cannot then read the file again without rewinding — the stream is sitting at the end. Either reopen it, or rewind:

file.clear();               // clear the eof flag
file.seekg(0);              // back to the start

Forgetting clear() is a classic trap: seekg does nothing while the eof flag is still set.

Do You Need to Close the File?

No. ifstream closes itself when it goes out of scope, which is the whole point of RAII. Call file.close() explicitly only if you need the handle released earlier than the end of the block.

Quick Reference

GoalCode
Read line by linewhile (std::getline(file, line))
Check open succeededif (!file) { ... }
Read into a vectorlines.push_back(line) in the loop
Split a line by commastd::getline(ss, field, ',')
Strip Windows \rif (line.back() == '\r') line.pop_back();
Rewind to the startfile.clear(); file.seekg(0);

Take Your C++ Further

If you want file handling, strings and the STL explained properly rather than pieced together from snippets, the C++ Better Explained Ebook covers the fundamentals in plain English. Just $19.

👉 Get the C++ Better Explained Ebook — $19


📋

Free Download: The 10 Mistakes Every C++ Beginner Makes

A free 1-page checklist that shows the exact traps that slow down every C++ beginner — so you can avoid them from day one.

🔒 No spam. Unsubscribe anytime.


Share this post on:

Written by

Sahil Bora

Software Engineer. Author and creator of C++ Better Explained.


Previous Post
How to Insert Into a Vector in C++ (insert, emplace, push_back)
Next Post
How to Replace a Substring in a C++ String

Keep Learning