9

I need to determin the byte size of a file.

The coding language is C++ and the code should work with Linux, windows and any other operating system. This implies using standard C or C++ functions/classes.

This trivial need has apparently no trivial solution.

hippietrail
  • 14,735
  • 16
  • 96
  • 147
chmike
  • 19,279
  • 21
  • 77
  • 99

8 Answers8

12

Using std's stream you can use:

std::ifstream ifile(....);
ifile.seekg(0, std::ios_base::end);//seek to end
//now get current position as length of file
ifile.tellg();

If you deal with write only file (std::ofstream), then methods are some another:

ofile.seekp(0, std::ios_base::end);
ofile.tellp();
Dewfy
  • 22,648
  • 12
  • 68
  • 116
  • 4
    Open the file in binary or you might get the wrong result. Text ifstreams could do `\r\n` to `\n` translation for instance. – MSalters Mar 11 '10 at 14:11
  • 1
    The problem is that tellg() returns a value of type streampos. It is usually an int, but it can also be another type. Though I'll keep it as an answer. – chmike Mar 11 '10 at 14:18
  • My answer actually reflects that fact because my first iteration was off the top of my head until someone pointed out the mistake and marked me down for it. – graham.reeds Mar 12 '10 at 11:34
  • 2
    Isn't an ifstream inefficient if you just want to get the file size? stat() will do it without having to open & seek. – richb Mar 12 '10 at 11:47
  • 1
    -1: Opening file is bad idea. Moreover, you cannot check size of, for example, `/etc/shadow` this way. – el.pescado - нет войне Jul 30 '10 at 17:54
  • To improve a bit on this method, if you seek file size just after opening, you can also do : std::ifstream ifile(..., std::ios_base::ate); It will put the cursor directly at the end of the file, and you gain 1 line of code :) – Jean-Michaël Celerier Jul 22 '13 at 06:53
  • File could be failed to open. -1 –  Nov 01 '18 at 15:38
6

You can use stat system call:

#ifdef WIN32 
_stat64()
#else
stat64()
Adil
  • 2,336
  • 7
  • 33
  • 38
2

If you only need the file size this is certainly overkill but in general I would go with Boost.Filesystem for platform-independent file operations. Amongst other attribute functions it contains

template <class Path> uintmax_t file_size(const Path& p);

You can find the reference here. Although Boost Libraries may seem huge I found it to often implement things very efficiently. You could also only extract the function you need but this might proof difficult as Boost is rather complex.

Sebastian
  • 2,586
  • 2
  • 22
  • 27
  • Why boost when there are already numerous ways to easily do this without boost? – Craig B May 16 '18 at 23:01
  • Chances are that if you work with files you might need more file functionality: boost is a good choice for that - standard body agrees and will add boost based library to STL. If you really only need file size - by all means use @Dewfy answer – Sebastian May 24 '18 at 09:04
1
std::intmax_t file_size(std::string_view const& fn)
{
  std::filebuf fb;

  return fb.open(fn.data(), std::ios::binary | std::ios::in) ?
    std::intmax_t(fb.pubseekoff({}, std::ios::end, std::ios::in)) :
    std::intmax_t(-1);
}

We sacrifice 1 bit for the error indicator and standard disclaimers apply when running on 32-bit systems. Use std::filesystem::file_size(), if possible, as std::filebuf may dynamically allocate buffers for file io. This would make all the iostream-based methods wasteful and slow. Files were/are meant to be streamed, though much more so in the past than today, which relegates file sizes to secondary importance.

Working example.

user1095108
  • 13,350
  • 9
  • 53
  • 103
0

Simples:

std::ifstream ifs; 
ifs.open("mybigfile.txt", std::ios::bin); 
ifs.seekg(0, std::ios::end); 
std::fpos pos = ifs.tellg();
graham.reeds
  • 15,795
  • 16
  • 68
  • 133
0

The prize for absolute inefficiency would go to:

auto file_size(std::string_view const& fn)
{
  std::ifstream ifs(fn.data(), std::ios::binary);

  return std::distance(std::istream_iterator<char>(ifs), {});
}

Example.

user1095108
  • 13,350
  • 9
  • 53
  • 103
-1

Often we want to get things done in the most portable manner, but in certain situations, especially like this, I would strongly recommend using system API's for best performance.

the100rabh
  • 4,047
  • 4
  • 31
  • 40
-1

Portability requires you to use the least common denominators, which would be C. (not c++) The method that I use is the following.

#include <stdio.h>

long filesize(const char *filename)
{
FILE *f = fopen(filename,"rb");  /* open the file in read only */

long size = 0;
  if (fseek(f,0,SEEK_END)==0) /* seek was successful */
      size = ftell(f);
  fclose(f);
  return size;
}
iplayfast
  • 120
  • 10