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
  • 15,848
  • 18
  • 99
  • 158
chmike
  • 20,922
  • 21
  • 83
  • 106

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
  • 23,277
  • 13
  • 73
  • 121
  • 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
  • @user707779 Don't downvote just for that, it is a simple example, when you're copying this code just add error checking. – Rafaelplayerxd YT Jul 14 '23 at 14:55
6

You can use stat system call:

#ifdef WIN32 
_stat64()
#else
stat64()
Adil
  • 2,418
  • 7
  • 34
  • 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,876
  • 2
  • 24
  • 28
  • 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
  • 14,119
  • 9
  • 58
  • 116
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
  • 16,230
  • 17
  • 74
  • 137
0

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
  • 140
  • 10
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
  • 14,119
  • 9
  • 58
  • 116
-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,077
  • 4
  • 32
  • 40