Portable way to get file size in C/C++
Asked Answered
S

8

10

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.

Synopsis answered 11/3, 2010 at 10:26 Comment(1)
#2283049Omit
S
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();
Skye answered 11/3, 2010 at 10:33 Comment(9)
Open the file in binary or you might get the wrong result. Text ifstreams could do \r\n to \n translation for instance.Dragonfly
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.Synopsis
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.Zoan
Isn't an ifstream inefficient if you just want to get the file size? stat() will do it without having to open & seek.Completion
-1: Opening file is bad idea. Moreover, you cannot check size of, for example, /etc/shadow this way.Bashee
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 :)Chane
File could be failed to open. -1Autolycus
@Autolycus Don't downvote just for that, it is a simple example, when you're copying this code just add error checking.Enrobe
@RafaelplayerxdYT That -1 was a bit much indeed, but it was still a very good catch that no amount of error checking could solve (before std::filesystem).Unquestioning
H
6

You can use stat system call:

#ifdef WIN32 
_stat64()
#else
stat64()
Hilleary answered 11/3, 2010 at 12:4 Comment(1)
It's worth noting that stat family of functions is part of POSIX, so they work on UNIX and UNIX-like systems as well.Bashee
G
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.

Giffer answered 11/3, 2010 at 11:41 Comment(2)
Why boost when there are already numerous ways to easily do this without boost?Callosity
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 @Skye answerGiffer
Z
1

Simples:

std::ifstream ifs; 
ifs.open("mybigfile.txt", std::ios::bin); 
ifs.seekg(0, std::ios::end); 
std::fpos pos = ifs.tellg();
Zoan answered 11/3, 2010 at 10:34 Comment(2)
On 32-bit systems, size_t is 32 bits. So this fails with files of 4GB or larger.Construction
I wrote this off the cuff with no reference. Looking at my code there are some problems which I have corrected.Zoan
D
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.

Deepfreeze answered 30/4, 2022 at 15:16 Comment(0)
Y
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;
}
Yong answered 30/7, 2010 at 17:28 Comment(2)
Too bad if you have a file >2GB in size on platforms with 32 bit long intPhysicochemical
@DavidHeffernan there are 64 bit versions of those functions. but that aside, this requires you to be able to open the file and is also a lot slower.Brittanybritte
D
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.

Deepfreeze answered 30/4, 2022 at 19:47 Comment(0)
O
-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.

Osmium answered 11/3, 2010 at 12:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.