143

Let's create a complementary question to this one. What is the most common way to get the file size in C++? Before answering, make sure it is portable (may be executed on Unix, Mac and Windows), reliable, easy to understand and without library dependencies (no boost or qt, but for instance glib is ok since it is portable library).

Community
  • 1
  • 1
Sophie Sperner
  • 4,068
  • 8
  • 30
  • 51
  • May dupicated with http://stackoverflow.com/questions/2409504 – Eric Z Apr 30 '11 at 07:10
  • 13
    Why no boost but allow glib? Boost is also portable. – rve Apr 30 '11 at 07:14
  • 2
    @mmutz: "Portable" has a different meaning than "standard". For example, Boost is more portable than standard C++ because it has workarounds for non-compliancies of compilers (including older versions). Fstat is portable in the strictest sense. – Thomas Edleson Apr 30 '11 at 23:44
  • 1
    @Thomas: There can be no "portable" without a standard. That standard may be in the form of a written document (like POSIX, or C++) and you hope that all implementations are true to it, or it may be by way of a common implementation that has been ported to many platforms (most libraries, incl. Boost). `fstat()` is standardized in POSIX, but Windows chose to deviate from that standard by calling the funciton `_fstat()`. `fstat()` is _not_ portable, because you need an `#ifdef _WIN32` to use it. – Marc Mutz - mmutz May 01 '11 at 06:39
  • Lots of boost functions are portable but needs to compile explicitly. – SmallChess Jun 12 '15 at 03:42

7 Answers7

159
#include <fstream>

std::ifstream::pos_type filesize(const char* filename)
{
    std::ifstream in(filename, std::ifstream::ate | std::ifstream::binary);
    return in.tellg(); 
}

See http://www.cplusplus.com/doc/tutorial/files/ for more information on files in C++.

edit: this answer is not correct since tellg() does not necessarily return the right value. See http://stackoverflow.com/a/22986486/1835769

Stefan
  • 42,026
  • 10
  • 73
  • 116
Spyros
  • 41,000
  • 23
  • 80
  • 121
  • Why do you need `std::ifstream::in ` here? There is no input to the stream at all. – qed Nov 04 '13 at 16:51
  • 3
    Or just get it from the file system with stat where the size is already maintained. No need to even open the file. – hookenz Jun 11 '14 at 20:06
  • 10
    Based on @jterm suggestion, opening the stream would be `std::ifstream in(filename, std::ios::binary | std::ios::ate);` Just to ease everybody's life ;) – jmpcm Nov 18 '14 at 11:41
  • 2
    Don't you need to close the file? – WillingGood Jan 26 '15 at 10:09
  • 4
    @WillingGood the file will be closed after returning of the function. – cfy Feb 05 '15 at 07:29
  • 3
    How to get the file size from tellg()??? – SmallChess Jun 12 '15 at 03:41
  • Just to let you know, this nice solution does not work in VS 2013 (up to Update5) in 64 bit for large files >4GB due to a bug in VC++ [1683089](https://connect.microsoft.com/VisualStudio/Feedback/Details/1683089). So better use seekg(0, end); and then tellg(); as a workaround until it's fixed. – x y Aug 24 '15 at 08:04
  • What will be the time complexity of this function? Will it be `O(1)` or `O(n)`, `n` being the size of file in bytes? – Anmol Singh Jaggi Oct 15 '15 at 13:24
  • 22
    This answer to a question on SO says that [tellg does not report the size of the file, nor the offset from the beginning in bytes.](http://stackoverflow.com/a/22986486/1835769) – displayName Oct 26 '15 at 20:38
  • 1
    is there a file size limitation with this approach? what's the size of the return value? – Solti Apr 04 '16 at 18:25
  • 1
    in addition to the 64 bit problem, this opens the file, which can have unwelcome side effects. better to use POSIX stat() (below) – Erik Aronesty Nov 08 '16 at 14:20
  • 4
    As mentioned above I don't think tellg() is guaranteed to return size, although it always has for me on linux systems I've done it on (so use at your own risk). – syntheticgio Jan 26 '17 at 18:43
  • Is it less efficient than `C` `stat()`? – kyb Jun 15 '17 at 20:42
  • 8
    this is missleading answer, since there is no way to convert pos_type to int/long – Stepan Yakovenko Jan 25 '18 at 10:28
  • 1
    This does not work for files provided by virtual filesystem driver s3fs (i.e. Amazon S3 files mounted using s3fs). `tellg()` returns a negative number – M.E. Jan 14 '21 at 17:15
97

While not necessarily the most popular method, I've heard that the ftell, fseek method may not always give accurate results in some circumstances. Specifically, if an already opened file is used and the size needs to be worked out on that and it happens to be opened as a text file, then it's going to give out wrong answers.

The following methods should always work as stat is part of the c runtime library on Windows, Mac and Linux.

long GetFileSize(std::string filename)
{
    struct stat stat_buf;
    int rc = stat(filename.c_str(), &stat_buf);
    return rc == 0 ? stat_buf.st_size : -1;
}

or 

long FdGetFileSize(int fd)
{
    struct stat stat_buf;
    int rc = fstat(fd, &stat_buf);
    return rc == 0 ? stat_buf.st_size : -1;
}

On some systems there is also a stat64/fstat64. So if you need this for very large files you may want to look at using those.

hookenz
  • 30,814
  • 37
  • 149
  • 251
55

Using the C++ filesystem library:

#include <filesystem>

int main(int argc, char *argv[]) {
  std::filesystem::path p{argv[1]};

  std::cout << "The size of " << p.u8string() << " is " <<
      std::filesystem::file_size(p) << " bytes.\n";
}
bames53
  • 79,748
  • 13
  • 162
  • 229
28

It is also possible to find that out using the fopen(),fseek() and ftell() function.

int get_file_size(std::string filename) // path to file
{
    FILE *p_file = NULL;
    p_file = fopen(filename.c_str(),"rb");
    fseek(p_file,0,SEEK_END);
    int size = ftell(p_file);
    fclose(p_file);
    return size;
}
Andro
  • 2,185
  • 1
  • 27
  • 34
  • 4
    You do not need `` and ``, you do need `` and you need error checking. (`fseek` segfaults when using a NULL file, ftell returns -1 on error) – rve Apr 30 '11 at 16:48
  • 4
    Initializing p_file and overwriting it in the next line is pointless and and makes many lints complain about "unused assignment". – Jens May 27 '12 at 19:26
  • Should you use `long` for the return type? – Progo Aug 15 '14 at 15:46
  • 5
    " Library implementations are allowed to not meaningfully support SEEK_END (therefore, code using it has no real standard portability)" – stephen May 20 '15 at 14:26
  • 1
    Related link: https://www.securecoding.cert.org/confluence/display/c/FIO19-C.+Do+not+use+fseek()+and+ftell()+to+compute+the+size+of+a+regular+file – rmobis Aug 11 '16 at 22:25
  • Do you need a null check? What happens if p_file is NULL? – Mary Ellen Bench Jun 21 '17 at 15:44
  • 1
    This answer is missleading and should be downvoted imho:https://wiki.sei.cmu.edu/confluence/display/c/FIO19-C.+Do+not+use+fseek%28%29+and+ftell%28%29+to+compute+the+size+of+a+regular+file – itMaxence Nov 08 '18 at 19:00
6
#include <stdio.h>
int main()
{
    FILE *f;
    f = fopen("mainfinal.c" , "r");
    fseek(f, 0, SEEK_END);
    unsigned long len = (unsigned long)ftell(f);
    printf("%ld\n", len);
    fclose(f);
}
Arc676
  • 4,196
  • 3
  • 26
  • 41
Sharon Joseph
  • 61
  • 1
  • 1
1

In c++ you can use following function, it will return the size of you file in bytes.

#include <fstream>

int fileSize(const char *add){
    ifstream mySource;
    mySource.open(add, ios_base::binary);
    mySource.seekg(0,ios_base::end);
    int size = mySource.tellg();
    mySource.close();
    return size;
}
Hadi Rasekh
  • 2,090
  • 2
  • 15
  • 24
  • this wouldn't work, you can't convert tellg output to int – Stepan Yakovenko Jan 25 '18 at 10:29
  • 1
    @StepanYakovenko take a look at this url http://www.cplusplus.com/reference/istream/istream/tellg/ – Hadi Rasekh Jan 26 '18 at 18:55
  • 2
    @HadiRasekh please stop using `cplusplus.com` for C++ reference, it's outdated beyond usability. Not only it lacks the newer stuff from C++14, C++17, C++20 and experimental TS, [it also has some considerable errors in some articles](https://stackoverflow.com/questions/6520052/whats-wrong-with-cplusplus-com). – bit2shift Sep 06 '18 at 12:50
0

The code snippet below exactly addresses the question in this post :)

///
/// Get me my file size in bytes (long long to support any file size supported by your OS.
///
long long Logger::getFileSize()
{
    std::streampos fsize = 0;

    std::ifstream myfile ("myfile.txt", ios::in);  // File is of type const char*

    fsize = myfile.tellg();         // The file pointer is currently at the beginning
    myfile.seekg(0, ios::end);      // Place the file pointer at the end of file

    fsize = myfile.tellg() - fsize;
    myfile.close();

    static_assert(sizeof(fsize) >= sizeof(long long), "Oops.");

    cout << "size is: " << fsize << " bytes.\n";
    return fsize;
}
Sammy
  • 237
  • 2
  • 7