开发者

Portable way to get file size in C/C++

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.


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();


You can use stat system call:

#ifdef WIN32 
_stat64()
#else
stat64()


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.


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.


Simples:

std::ifstream ifs; 
ifs.open("mybigfile.txt", std::ios::bin); 
ifs.seekg(0, std::ios::end); 
std::fpos pos = ifs.tellg();


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.


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.


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;
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜