Skip to content
C++ Better Explained
Go back
How to Get the Size of a File in C++

How to Get the Size of a File in C++

Short answer (C++17):

#include <filesystem>
auto bytes = std::filesystem::file_size("data.txt");

No opening, no seeking, no stream state to manage. On older compilers, use the seekg/tellg approach further down.


The Modern Way: std::filesystem

#include <iostream>
#include <filesystem>

int main() {
    std::filesystem::path p = "data.txt";

    if (!std::filesystem::exists(p)) {
        std::cerr << "File does not exist\n";
        return 1;
    }

    std::uintmax_t bytes = std::filesystem::file_size(p);
    std::cout << bytes << " bytes\n";
}

file_size asks the operating system directly, so it does not read the contents and costs the same whether the file is 1 KB or 1 GB.

Note the return type: std::uintmax_t, the largest unsigned integer the platform has. Files can exceed what an int holds, so do not narrow it casually.

Handling Errors Without Exceptions

file_size throws std::filesystem::filesystem_error if the path is missing or unreadable. If you would rather not use try/catch, there is an overload that reports through an error code:

#include <filesystem>
#include <system_error>

std::error_code ec;
auto bytes = std::filesystem::file_size("data.txt", ec);

if (ec) {
    std::cerr << "Error: " << ec.message() << '\n';
} else {
    std::cout << bytes << " bytes\n";
}

This is the version I would reach for in real code β€” a missing file is an ordinary situation, not an exceptional one.

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

The Pre-C++17 Way: seekg and tellg

#include <iostream>
#include <fstream>

std::streamsize fileSize(const std::string& path) {
    std::ifstream file(path, std::ios::binary | std::ios::ate);
    if (!file) return -1;
    return file.tellg();
}

int main() {
    auto size = fileSize("data.txt");
    if (size < 0) std::cerr << "Could not open\n";
    else std::cout << size << " bytes\n";
}

std::ios::ate positions the read head at the end on open, and tellg() reports that position β€” which is the length.

The std::ios::binary flag is not optional here. In text mode on Windows, \r\n sequences are translated during reading, so the position you get back does not match the actual byte count on disk. Binary mode disables that translation.

If you need the size and then want to read from the start:

std::ifstream file("data.txt", std::ios::binary | std::ios::ate);
auto size = file.tellg();
file.seekg(0);                 // rewind before reading

Checking if a File Is Empty

// C++17
if (std::filesystem::file_size(p) == 0) {
    std::cout << "Empty\n";
}

// any version, using the stream
std::ifstream file("data.txt");
if (file.peek() == std::ifstream::traits_type::eof()) {
    std::cout << "Empty\n";
}

peek() looks at the next character without consuming it, so the stream is still usable afterwards.

Formatting Bytes as KB and MB

Raw byte counts are hard to read:

#include <iomanip>
#include <sstream>
#include <string>

std::string humanSize(std::uintmax_t bytes) {
    const char* units[] = {"B", "KB", "MB", "GB", "TB"};
    int i = 0;
    double size = static_cast<double>(bytes);

    while (size >= 1024.0 && i < 4) {
        size /= 1024.0;
        ++i;
    }

    std::ostringstream ss;
    ss << std::fixed << std::setprecision(i == 0 ? 0 : 1)
       << size << ' ' << units[i];
    return ss.str();
}

int main() {
    std::cout << humanSize(2048)     << '\n';   // 2.0 KB
    std::cout << humanSize(1536000)  << '\n';   // 1.5 MB
}

Reading a Whole File Using Its Size

A common reason to want the size is pre-allocating a buffer:

#include <fstream>
#include <string>

std::string readWholeFile(const std::string& path) {
    std::ifstream file(path, std::ios::binary | std::ios::ate);
    if (!file) return "";

    auto size = file.tellg();
    std::string content(static_cast<size_t>(size), '\0');

    file.seekg(0);
    file.read(&content[0], size);
    return content;
}

Allocating once up front is much faster than appending line by line for large files. For line-oriented processing, reading line by line is still the right tool.

Quick Reference

GoalCode
Size (C++17)std::filesystem::file_size(p)
Size, no exceptionsfile_size(p, ec)
Size (older C++)open with binary|ate, then tellg()
Is it emptyfile_size(p) == 0
Does it existstd::filesystem::exists(p)
Rewind after sizingfile.seekg(0)

Take Your C++ Further

If you want file handling and the rest of the fundamentals explained properly rather than gathered from snippets, the C++ Better Explained Ebook covers it 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 Trim Whitespace from a String in C++
Next Post
cin vs getline in C++: Why getline Gets Skipped

Keep Learning